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
new file mode 100644
index 0000000..894e0e4
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,167 @@
+analyzer:
+ exclude:
+
+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_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/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
diff --git a/lib/bloc/database/database_bloc.dart b/lib/bloc/database/database_bloc.dart
deleted file mode 100644
index 37d338c..0000000
--- a/lib/bloc/database/database_bloc.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-
-import 'package:bloc/bloc.dart';
-
-import './database_event.dart';
-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';
-
-class DatabaseBloc extends Bloc {
-
- DatabaseBloc() : super(DatabaseDisconnected());
-
- @override
- Stream mapEventToState(DatabaseEvent event)
- async* {
- if (event is ConnectedToDatabase) {
- yield DatabaseConnected(event.database);
- } else {
- yield DatabaseDisconnected();
- }
- }
-
-}
\ No newline at end of file
diff --git a/lib/bloc/database/database_event.dart b/lib/bloc/database/database_event.dart
deleted file mode 100644
index 0b65487..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();
-}
\ 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
deleted file mode 100644
index d062330..0000000
--- a/lib/bloc/database/database_not_connected_exception.dart
+++ /dev/null
@@ -1 +0,0 @@
-class DatabaseNotConnectedException implements Exception {}
\ No newline at end of file
diff --git a/lib/bloc/database/database_state.dart b/lib/bloc/database/database_state.dart
deleted file mode 100644
index 042443f..0000000
--- a/lib/bloc/database/database_state.dart
+++ /dev/null
@@ -1,15 +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();
-}
\ No newline at end of file
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/bloc/theme/theme_bloc.dart b/lib/bloc/theme/theme_bloc.dart
index 49167b7..b34b5a7 100644
--- a/lib/bloc/theme/theme_bloc.dart
+++ b/lib/bloc/theme/theme_bloc.dart
@@ -1,10 +1,10 @@
-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:get_it/get_it.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';
@@ -12,24 +12,20 @@ part 'theme_event.dart';
part 'theme_state.dart';
class ThemeBloc extends Bloc {
- bool prefsAreLoaded = false;
+ ThemeBloc() : super(const LightThemeState()) {
+ on(
+ (event, emit) => emit(
+ event.themeIsDark ? const DarkThemeState() : const LightThemeState(),
+ ),
+ );
- ThemeBloc() : super(LightThemeState()) {
- SharedPreferences.getInstance().then((prefs) {
- this.prefsAreLoaded = true;
- this.add(
- SetTheme(
- themeIsDark: prefs.getBool('darkThemeEnabled') ?? false,
- ),
- );
- });
- }
-
- @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 d4bb021..134e0c6 100644
--- a/lib/bloc/theme/theme_state.dart
+++ b/lib/bloc/theme/theme_state.dart
@@ -2,25 +2,21 @@ part of 'theme_bloc.dart';
@immutable
abstract class ThemeState {
- final bool prefsAreLoaded;
-
- const ThemeState(this.prefsAreLoaded);
+ const ThemeState();
AppTheme get theme;
}
class LightThemeState extends ThemeState {
- final bool prefsAreLoaded;
-
- const LightThemeState({this.prefsAreLoaded = false}) : super(prefsAreLoaded);
+ const LightThemeState();
+ @override
AppTheme get theme => LightTheme();
}
class DarkThemeState extends ThemeState {
- final bool prefsAreLoaded;
-
- const DarkThemeState({this.prefsAreLoaded = false}) : super(prefsAreLoaded);
+ const DarkThemeState();
+ @override
AppTheme get theme => DarkTheme();
-}
\ No newline at end of file
+}
diff --git a/lib/main.dart b/lib/main.dart
index 8210f71..31529b0 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,180 +1,57 @@
+import 'dart:io';
+
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:mdi/mdi.dart';
-import 'package:path_provider/path_provider.dart';
+import 'package:get_it/get_it.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 'package:jisho_study_tool/objectbox.g.dart';
+import 'bloc/theme/theme_bloc.dart';
+import 'router.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/history.dart';
-import 'package:jisho_study_tool/view/screens/search/view.dart';
-import 'package:jisho_study_tool/view/screens/settings.dart';
-
-import 'models/themes/theme.dart';
-
-void main() => runApp(MyApp());
-
-DatabaseBloc _databaseBloc = DatabaseBloc();
-
-class MyApp extends StatefulWidget {
- @override
- _MyAppState createState() => _MyAppState();
+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);
}
-class _MyAppState extends State {
- late final Store _store;
- bool dbConnected = false;
+Future setupSharedPreferences() async {
+ final SharedPreferences prefs = await SharedPreferences.getInstance();
+ GetIt.instance.registerSingleton(prefs);
+}
- @override
- void initState() {
- super.initState();
+Future main() async {
+ WidgetsFlutterBinding.ensureInitialized();
- getApplicationDocumentsDirectory().then((dir) {
- _store = Store(
- getObjectBoxModel(),
- directory: join(dir.path, 'objectbox'),
- );
+ await Future.wait([
+ setupDatabase(),
+ setupSharedPreferences(),
+ ]);
- _databaseBloc.add(ConnectedToDatabase(_store));
- setState(() {
- dbConnected = true;
- });
- });
- }
+ runApp(const MyApp());
+}
- @override
- void dispose() {
- _store.close();
- _databaseBloc.add(DisconnectedFromDatabase());
- super.dispose();
- }
+class MyApp extends StatelessWidget {
+ const MyApp({Key? key}) : super(key: key);
@override
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) {
- return MaterialApp(
- title: 'Jisho Study Tool',
- theme: themeState.theme.getMaterialTheme(),
- home: dbConnected && themeState.prefsAreLoaded
- ? Home()
- : SplashScreen(),
- );
- },
+ builder: (context, themeState) => MaterialApp(
+ title: 'Jisho Study Tool',
+ theme: themeState.theme.getMaterialTheme(),
+ initialRoute: '/',
+ onGenerateRoute: generateRoute,
+ ),
),
);
}
}
-
-class Home extends StatelessWidget {
- @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,
- ),
- 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,
- ),
- );
- },
- );
- },
- );
- }
-}
-
-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 = [
- _Page(
- content: SearchView(),
- titleBar: Text('Search'),
- item: BottomNavigationBarItem(
- label: 'Search',
- icon: Icon(Icons.search),
- ),
- ),
- _Page(
- content: KanjiView(),
- titleBar: KanjiViewBar(),
- item: BottomNavigationBarItem(
- label: 'Kanji', icon: Icon(Mdi.ideogramCjk, size: 30)),
- ),
- _Page(
- content: HistoryView(),
- titleBar: Text("History"),
- item: BottomNavigationBarItem(
- label: 'History',
- icon: Icon(Icons.history),
- ),
- ),
- _Page(
- content: Container(),
- titleBar: Text("Saved"),
- item: BottomNavigationBarItem(
- label: 'Saved',
- icon: Icon(Icons.bookmark),
- ),
- ),
- _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 f371573..2de2096 100644
--- a/lib/models/history/search.dart
+++ b/lib/models/history/search.dart
@@ -1,30 +1,42 @@
-import 'package:objectbox/objectbox.dart';
+import 'package:sembast/sembast.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;
+ Search.fromKanjiQuery({
+ required this.timestamp,
+ required KanjiQuery this.kanjiQuery,
+ }) : wordQuery = null;
- final wordQuery = ToOne();
+ Search.fromWordQuery({
+ required this.timestamp,
+ required WordQuery this.wordQuery,
+ }) : kanjiQuery = null;
- final kanjiQuery = ToOne();
+ bool get isKanji => wordQuery == null;
- Search({
- this.id = 0,
- required this.timestamp
- }); // {
+ Map toJson() => {
+ 'timestamp': timestamp.millisecondsSinceEpoch,
+ 'wordQuery': wordQuery?.toJson(),
+ 'kanjiQuery': kanjiQuery?.toJson(),
+ };
- bool isKanji() {
- // // TODO: better error message
- if (this.wordQuery.target == null && this.kanjiQuery.target == null)
- throw Exception();
-
- return this.wordQuery.target == null;
- }
+ 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']),
+ );
-}
\ No newline at end of file
+ static StoreRef get store => intMapStoreFactory.store('search');
+}
diff --git a/lib/models/history/word_query.dart b/lib/models/history/word_query.dart
index 6041b00..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,
});
-}
\ No newline at end of file
+
+ 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 75d1f5c..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';
-import 'package:jisho_study_tool/models/history/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,
});
-}
\ No newline at end of file
+}
diff --git a/lib/models/storage/common.dart b/lib/models/storage/common.dart
new file mode 100644
index 0000000..6aeeb7c
--- /dev/null
+++ b/lib/models/storage/common.dart
@@ -0,0 +1,22 @@
+// import 'package:objectbox/objectbox.dart';
+// import 'package:unofficial_jisho_api/api.dart' as jisho;
+
+// TODO: Rewrite for sembast
+
+// @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
new file mode 100644
index 0000000..58e7d2c
--- /dev/null
+++ b/lib/models/storage/example.dart
@@ -0,0 +1,58 @@
+// import 'package:objectbox/objectbox.dart';
+// import 'package:unofficial_jisho_api/api.dart' as jisho;
+
+// import 'common.dart';
+
+// TODO: Rewrite for sembast
+
+// @Entity()
+// class ExampleResultData {
+// int id;
+// String kanji;
+// String kana;
+// String english;
+// List pieces;
+
+// ExampleResultData({
+// this.id = 0,
+// required this.kanji,
+// required this.kana,
+// required this.english,
+// required this.pieces,
+// });
+
+// 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
new file mode 100644
index 0000000..28f324b
--- /dev/null
+++ b/lib/models/storage/kanji_result.dart
@@ -0,0 +1,129 @@
+// import 'package:objectbox/objectbox.dart';
+// import 'package:unofficial_jisho_api/api.dart' as jisho;
+
+// TODO: Rewrite for sembast
+
+// @Entity()
+// class YomiExample {
+// int id;
+// String example;
+// String reading;
+// String meaning;
+
+// YomiExample({
+// this.id = 0,
+// required this.example,
+// required this.reading,
+// required this.meaning,
+// });
+
+// YomiExample.fromJishoObject(jisho.YomiExample object)
+// : id = 0,
+// example = object.example,
+// reading = object.reading,
+// meaning = object.meaning;
+// }
+
+// @Entity()
+// class Radical {
+// int id = 0;
+// String symbol;
+// List forms;
+// String meaning;
+
+// Radical({
+// this.id = 0,
+// required this.symbol,
+// required this.forms,
+// required this.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({
+// 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
new file mode 100644
index 0000000..c02eae7
--- /dev/null
+++ b/lib/models/storage/scrape_result.dart
@@ -0,0 +1,155 @@
+// import 'package:objectbox/objectbox.dart';
+// import 'package:unofficial_jisho_api/api.dart' as jisho;
+
+// import 'common.dart';
+
+// TODO: Rewrite for sembast
+
+// @Entity()
+// class PhraseScrapeSentence {
+// int id;
+// String english;
+// String japanese;
+// List pieces;
+
+// PhraseScrapeSentence({
+// this.id = 0,
+// required this.english,
+// required this.japanese,
+// required this.pieces,
+// });
+
+// PhraseScrapeSentence.fromJishoObject(jisho.PhraseScrapeSentence object)
+// : id = 0,
+// english = object.english,
+// japanese = object.japanese,
+// pieces = object.pieces
+// .map((p) => ExampleSentencePiece.fromJishoObject(p))
+// .toList();
+// }
+
+// @Entity()
+// class PhraseScrapeMeaning {
+// int id;
+// List seeAlsoTerms;
+// List sentences;
+// String definition;
+// List supplemental;
+// String? definitionAbstract;
+// List tags;
+
+// PhraseScrapeMeaning({
+// this.id = 0,
+// required this.seeAlsoTerms,
+// required this.sentences,
+// required this.definition,
+// required this.supplemental,
+// required this.definitionAbstract,
+// required this.tags,
+// });
+
+// 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;
+// }
+
+// @Entity()
+// class KanjiKanaPair {
+// int id;
+// String kanji;
+// String? kana;
+
+// KanjiKanaPair({
+// this.id = 0,
+// required this.kanji,
+// required this.kana,
+// });
+
+// KanjiKanaPair.fromJishoObject(jisho.KanjiKanaPair object)
+// : id = 0,
+// kanji = object.kanji,
+// kana = object.kana;
+// }
+
+// @Entity()
+// class PhrasePageScrapeResult {
+// int id;
+// bool found;
+// String query;
+// PhrasePageScrapeResultData? data;
+
+// 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 7d1e5d3..3f6738b 100644
--- a/lib/models/storage/search_result.dart
+++ b/lib/models/storage/search_result.dart
@@ -1,72 +1,195 @@
// import 'package:objectbox/objectbox.dart';
// import 'package:unofficial_jisho_api/api.dart' as jisho;
+// TODO: Rewrite for sembast
+
// @Entity()
// class SearchResult {
-// int id = 0;
-// final meta = ToOne();
-// final data = ToMany();
+// int id;
+// final JishoResultMeta meta;
+// final ToMany data;
-// // SearchResult(JishoAPIResult result) {
-// // this.data = result.data;
-// // this.meta = result.meta;
-// // }
+// SearchResult({
+// this.id = 0,
+// required this.meta,
+// required this.data,
+// });
-// // JishoAPIResult toJishoAPIResult() {
-// // return JishoAPIResult(meta: this.meta, data: this.data);
-// // }
+// 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 JishoResultMeta {
-// int id = 0;
+// int id;
// int status;
+
+// JishoResultMeta({
+// this.id = 0,
+// required this.status,
+// });
+
+// JishoResultMeta.fromJishoObject(final jisho.JishoResultMeta object)
+// : id = 0,
+// status = object.status;
// }
// @Entity()
// class JishoResult {
-// int id = 0;
-// final attribution = ToOne();
-// bool is_common;
-// final japanese = ToMany();
+// int id;
+// JishoAttribution attribution;
+// bool? is_common;
+// List japanese;
// List jlpt;
-// final senses = ToMany();
+// List senses;
// String slug;
// List tags;
+
+// 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,
+// });
+
+// 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 JishoAttribution {
-// int id = 0;
-// String dbpedia;
-// String jmdict;
+// int id;
+// String? dbpedia;
+// bool jmdict;
// bool jmnedict;
+
+// JishoAttribution({
+// this.id = 0,
+// required this.dbpedia,
+// required this.jmdict,
+// required this.jmnedict,
+// });
+
+// JishoAttribution.fromJishoObject(final jisho.JishoAttribution object)
+// : id = 0,
+// dbpedia = object.dbpedia,
+// jmdict = object.jmdict,
+// jmnedict = object.jmnedict;
// }
// @Entity()
// class JishoJapaneseWord {
-// int id = 0;
-// String reading;
-// String word;
+// int id;
+// String? reading;
+// String? word;
+
+// JishoJapaneseWord({
+// this.id = 0,
+// required this.reading,
+// required this.word,
+// });
+
+// JishoJapaneseWord.fromJishoObject(final jisho.JishoJapaneseWord object)
+// : id = 0,
+// reading = object.reading,
+// word = object.word;
// }
// @Entity()
// class JishoWordSense {
-// int id = 0;
+// int id;
// List antonyms;
// List english_definitions;
// List info;
-// final links = ToMany();
+// List links;
// List parts_of_speech;
// List restrictions;
// List see_also;
-// List source;
+// 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 = 0;
+// 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/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..705be40 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,17 @@ 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;
+ 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);
}
- 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 +66,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/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/router.dart b/lib/router.dart
new file mode 100644
index 0000000..5b9b5ce
--- /dev/null
+++ b/lib/router.dart
@@ -0,0 +1,31 @@
+import 'package:flutter/material.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) {
+ final args = settings.arguments;
+
+ switch (settings.name) {
+ case '/':
+ return MaterialPageRoute(builder: (_) => const 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: (_) => 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 eb1e379..3459bda 100644
--- a/lib/services/jisho_api/jisho_search.dart
+++ b/lib/services/jisho_api/jisho_search.dart
@@ -1,5 +1,6 @@
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 2c55d61..76e8a31 100644
--- a/lib/services/jisho_api/kanji_search.dart
+++ b/lib/services/jisho_api/kanji_search.dart
@@ -1,17 +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];
}
@@ -23,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/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 55%
rename from lib/view/screens/loading.dart
rename to lib/view/components/common/loading.dart
index 327c44c..2f30fff 100644
--- a/lib/view/screens/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/screens/splash.dart b/lib/view/components/common/splash.dart
similarity index 62%
rename from lib/view/screens/splash.dart
rename to lib/view/components/common/splash.dart
index 350d7d2..e453f34 100644
--- a/lib/view/screens/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.asset('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/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/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 eb7be2f..15ce4c5 100644
--- a/lib/view/components/history/kanji_search_item.dart
+++ b/lib/view/components/history/kanji_search_item.dart
@@ -1,12 +1,10 @@
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';
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;
@@ -15,13 +13,14 @@ 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(
aspectRatio: 1,
child: Container(
- padding: EdgeInsets.all(5),
+ padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: _menuColors.background,
borderRadius: BorderRadius.circular(10.0),
@@ -56,27 +55,30 @@ class KanjiSearchItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Slidable(
+ 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: () {
- BlocProvider.of(context).add(ChangePage(1));
- BlocProvider.of(context).add(GetKanji(this.result.kanji));
+ Navigator.pushNamed(context, '/kanjiSearch', arguments: result.kanji);
},
time: timestamp,
search: _KanjiBox(result.kanji),
),
- actionPane: SlidableScrollActionPane(),
- secondaryActions: [
- IconSlideAction(
- caption: "Favourite",
- color: Colors.yellow,
- icon: Icons.star,
- ),
- IconSlideAction(
- caption: "Delete",
- color: Colors.red,
- icon: Icons.delete,
- ),
- ],
);
}
}
diff --git a/lib/view/components/history/phrase_search_item.dart b/lib/view/components/history/phrase_search_item.dart
index 30273bd..d6d4377 100644
--- a/lib/view/components/history/phrase_search_item.dart
+++ b/lib/view/components/history/phrase_search_item.dart
@@ -1,10 +1,8 @@
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';
+import '../../../models/history/word_query.dart';
class PhraseSearchItem extends StatelessWidget {
final WordQuery search;
@@ -19,16 +17,25 @@ class PhraseSearchItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Slidable(
- actionPane: SlidableScrollActionPane(),
- secondaryActions: [
- IconSlideAction(
- caption: "Delete", color: Colors.red, icon: Icons.delete)
- ],
+ endActionPane: ActionPane(
+ motion: const ScrollMotion(),
+ children: [
+
+ SlidableAction(
+ label: 'Delete',
+ backgroundColor: Colors.red,
+ icon: Icons.delete,
+ onPressed: (_) {},
+ ),
+ ],
+
+ ),
child: SearchItem(
- onTap: () {
- BlocProvider.of(context).add(ChangePage(0));
- BlocProvider.of(context).add(GetSearchResults(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
new file mode 100644
index 0000000..f94c128
--- /dev/null
+++ b/lib/view/components/kanji/kanji_result_body.dart
@@ -0,0 +1,101 @@
+import 'package:flutter/material.dart';
+import 'package:unofficial_jisho_api/api.dart' as jisho;
+
+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 KanjiResultBody extends StatelessWidget {
+ late final String query;
+ late final jisho.KanjiResultData resultData;
+
+ 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();
+
+ resultData = result.data!;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return ListView(
+ children: [
+ Container(
+ margin: const EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 30.0),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ const Flexible(
+ fit: FlexFit.tight,
+ child: Center(child: SizedBox()),
+ ),
+ Flexible(
+ fit: FlexFit.tight,
+ child: Center(child: Header(kanji: query)),
+ ),
+ Flexible(
+ fit: FlexFit.tight,
+ child: Center(
+ child: (resultData.radical != null)
+ ? Radical(radical: resultData.radical!)
+ : const SizedBox(),
+ ),
+ ),
+ ],
+ ),
+ ),
+ 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(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(
+ onyomi: resultData.onyomiExamples,
+ kunyomi: resultData.kunyomiExamples,
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/view/components/kanji/result/examples.dart b/lib/view/components/kanji/kanji_result_body/examples.dart
similarity index 54%
rename from lib/view/components/kanji/result/examples.dart
rename to lib/view/components/kanji/kanji_result_body/examples.dart
index 9f4b78e..8740336 100644
--- a/lib/view/components/kanji/result/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/result/grade.dart b/lib/view/components/kanji/kanji_result_body/grade.dart
similarity index 77%
rename from lib/view/components/kanji/result/grade.dart
rename to lib/view/components/kanji/kanji_result_body/grade.dart
index 12fb36e..abe2443 100644
--- a/lib/view/components/kanji/result/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/result/header.dart b/lib/view/components/kanji/kanji_result_body/header.dart
similarity index 70%
rename from lib/view/components/kanji/result/header.dart
rename to lib/view/components/kanji/kanji_result_body/header.dart
index d0f999c..c86fb5d 100644
--- a/lib/view/components/kanji/result/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/result/jlpt_level.dart b/lib/view/components/kanji/kanji_result_body/jlpt_level.dart
similarity index 62%
rename from lib/view/components/kanji/result/jlpt_level.dart
rename to lib/view/components/kanji/kanji_result_body/jlpt_level.dart
index 2cc2fe1..f63cbc3 100644
--- a/lib/view/components/kanji/result/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/result/radical.dart b/lib/view/components/kanji/kanji_result_body/radical.dart
similarity index 78%
rename from lib/view/components/kanji/result/radical.dart
rename to lib/view/components/kanji/kanji_result_body/radical.dart
index d208e00..aa7ef1e 100644
--- a/lib/view/components/kanji/result/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/result/rank.dart b/lib/view/components/kanji/kanji_result_body/rank.dart
similarity index 78%
rename from lib/view/components/kanji/result/rank.dart
rename to lib/view/components/kanji/kanji_result_body/rank.dart
index 24356fb..89279ac 100644
--- a/lib/view/components/kanji/result/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/result/stroke_order_gif.dart b/lib/view/components/kanji/kanji_result_body/stroke_order_gif.dart
similarity index 70%
rename from lib/view/components/kanji/result/stroke_order_gif.dart
rename to lib/view/components/kanji/kanji_result_body/stroke_order_gif.dart
index ecda698..75fb00d 100644
--- a/lib/view/components/kanji/result/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
new file mode 100644
index 0000000..ce5eb20
--- /dev/null
+++ b/lib/view/components/kanji/kanji_result_body/yomi_chips.dart
@@ -0,0 +1,125 @@
+import 'package:flutter/material.dart';
+
+import '../../../../bloc/theme/theme_bloc.dart';
+
+enum YomiType {
+ onyomi,
+ kunyomi,
+ meaning,
+}
+
+extension on YomiType {
+ String get title {
+ switch (this) {
+ case YomiType.onyomi:
+ return 'Onyomi';
+ case YomiType.kunyomi:
+ return 'Kunyomi';
+ case YomiType.meaning:
+ return 'Meanings';
+ }
+ }
+
+ ColorSet getColors(BuildContext context) {
+ final theme = BlocProvider.of(context).state.theme;
+
+ switch (this) {
+ case YomiType.onyomi:
+ return theme.onyomiColor;
+ case YomiType.kunyomi:
+ return theme.kunyomiColor;
+ case YomiType.meaning:
+ return theme.menuGreyNormal;
+ }
+ }
+}
+
+class YomiChips extends StatelessWidget {
+ final List yomi;
+ final YomiType type;
+
+ const YomiChips({
+ required this.yomi,
+ required this.type,
+ Key? key,
+ }) : super(key: key);
+
+ bool get 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 = yomi
+ .map(
+ (y) => yomiCard(
+ context: context,
+ yomi: y,
+ colors: type.getColors(context),
+ ),
+ )
+ .toList();
+
+ if (!isExpandable)
+ return Wrap(
+ runSpacing: 10.0,
+ children: yomiCards,
+ );
+ else
+ return ExpansionTile(
+ // initiallyExpanded: false,
+ title: Center(
+ child: yomiCard(
+ context: context,
+ yomi: type.title,
+ colors: type.getColors(context),
+ ),
+ ),
+ children: [
+ const SizedBox(
+ height: 20.0,
+ ),
+ Wrap(
+ runSpacing: 10.0,
+ children: yomiCards,
+ ),
+ const SizedBox(
+ height: 25.0,
+ ),
+ ],
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ margin: const EdgeInsets.symmetric(
+ horizontal: 10.0,
+ vertical: 5.0,
+ ),
+ alignment: Alignment.centerLeft,
+ child: yomiWrapper(context),
+ );
+ }
+}
diff --git a/lib/view/components/kanji/kanji_search_bar.dart b/lib/view/components/kanji/kanji_search_bar.dart
deleted file mode 100644
index fba6409..0000000
--- a/lib/view/components/kanji/kanji_search_bar.dart
+++ /dev/null
@@ -1,71 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:jisho_study_tool/bloc/kanji/kanji_bloc.dart';
-
-class KanjiSearchBar extends StatefulWidget {
-
- const KanjiSearchBar();
-
- @override
- _KanjiSearchBarState createState() => new _KanjiSearchBarState();
-}
-
-enum TextFieldButton {clear, paste}
-
-class _KanjiSearchBarState extends State {
- final TextEditingController textController = new TextEditingController();
- TextFieldButton button = TextFieldButton.paste;
-
- @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 _pasteText() async {
- ClipboardData? clipboardData = await Clipboard.getData('text/plain');
- if (clipboardData != null && clipboardData.text != null) {
- textController.text = clipboardData.text!;
- updateSuggestions();
- }
- }
-
- @override
- Widget build(BuildContext context) {
- IconButton clearButton = IconButton(
- icon: Icon(Icons.clear),
- onPressed: () => _clearText(),
- );
-
- IconButton pasteButton = IconButton(
- icon: Icon(Icons.content_paste),
- onPressed: () => _pasteText(),
- );
-
- return TextField(
- controller: textController,
- onChanged: (text) => _getKanjiSuggestions(text),
- onSubmitted: (_) => {},
- decoration: new InputDecoration(
- prefixIcon: Icon(Icons.search),
- hintText: 'Search',
- // fillColor: Colors.white,
- // filled: true,
- border: OutlineInputBorder(
- borderRadius: BorderRadius.circular(10.0),
- ),
- isDense: false,
- suffixIcon: (button == TextFieldButton.clear) ? clearButton : pasteButton,
- ),
- );
- }
-}
\ No newline at end of file
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..3ba2e76
--- /dev/null
+++ b/lib/view/components/kanji/kanji_search_body.dart
@@ -0,0 +1,108 @@
+import 'package:animated_size_and_fade/animated_size_and_fade.dart';
+import 'package:flutter/material.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 {
+ const 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: const 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: const BoxDecoration(),
+ alignment: Alignment.center,
+ padding: const EdgeInsets.symmetric(horizontal: 20),
+ child: AnimatedBuilder(
+ animation: _searchbarMovementAnimation,
+ builder: (context, _) {
+ return Container(
+ alignment: _searchbarMovementAnimation.value,
+ padding: const 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(() {
+ suggestions = kanjiSuggestions(text);
+ }),
+ ),
+ ),
+ AnimatedSizeAndFade(
+ 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_grid.dart b/lib/view/components/kanji/kanji_search_body/kanji_grid.dart
similarity index 55%
rename from lib/view/components/kanji/kanji_grid.dart
rename to lib/view/components/kanji/kanji_search_body/kanji_grid.dart
index 5ea3802..8373be9 100644
--- a/lib/view/components/kanji/kanji_grid.dart
+++ b/lib/view/components/kanji/kanji_search_body/kanji_grid.dart
@@ -1,16 +1,16 @@
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';
+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,
),
@@ -33,29 +33,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: const 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_body/kanji_search_bar.dart b/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart
new file mode 100644
index 0000000..ce1b806
--- /dev/null
+++ b/lib/view/components/kanji/kanji_search_body/kanji_search_bar.dart
@@ -0,0 +1,73 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+class KanjiSearchBar extends StatefulWidget {
+ final Function(String)? onChanged;
+
+ const KanjiSearchBar({this.onChanged, Key? key}) : super(key: key);
+
+ @override
+ KanjiSearchBarState createState() => KanjiSearchBarState();
+}
+
+enum TextFieldButton { clear, paste }
+
+class KanjiSearchBarState extends State {
+ final TextEditingController textController = TextEditingController();
+ TextFieldButton button = TextFieldButton.paste;
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ void runOnChanged() {
+ if (widget.onChanged != null) widget.onChanged!(textController.text);
+ }
+
+ void clearText() {
+ textController.text = '';
+ runOnChanged();
+ }
+
+ Future pasteText() async {
+ final ClipboardData? clipboardData = await Clipboard.getData('text/plain');
+ if (clipboardData != null && clipboardData.text != null) {
+ textController.text = clipboardData.text!;
+ runOnChanged();
+ }
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final IconButton clearButton = IconButton(
+ icon: const Icon(Icons.clear),
+ onPressed: () => clearText(),
+ );
+
+ final IconButton pasteButton = IconButton(
+ icon: const Icon(Icons.content_paste),
+ onPressed: () => pasteText(),
+ );
+
+ return TextField(
+ controller: textController,
+ onChanged: (text) {
+ if (widget.onChanged != null) widget.onChanged!(text);
+ },
+ onSubmitted: (_) => {},
+ decoration: InputDecoration(
+ prefixIcon: const Icon(Icons.search),
+ hintText: 'Search',
+ // fillColor: Colors.white,
+ // filled: true,
+ border: OutlineInputBorder(
+ borderRadius: BorderRadius.circular(10.0),
+ ),
+ isDense: false,
+ suffixIcon:
+ (button == TextFieldButton.clear) ? clearButton : pasteButton,
+ ),
+ );
+ }
+}
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 65%
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..23aad34 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
@@ -13,25 +12,22 @@ class KanjiSearchOptionsBar extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
_IconButton(
- icon: Text(
- "部",
+ icon: const Text(
+ '部',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 18,
),
),
- onPressed: () =>
- BlocProvider.of(context).add(ReturnToInitialState()),
+ onPressed: () {},
),
_IconButton(
- icon: Icon(Icons.category),
- onPressed: () =>
- BlocProvider.of(context).add(ReturnToInitialState()),
+ icon: const Icon(Icons.category),
+ onPressed: () {},
),
_IconButton(
- icon: Icon(Icons.mode),
- onPressed: () =>
- BlocProvider.of(context).add(ReturnToInitialState()),
+ icon: const Icon(Icons.mode),
+ onPressed: () {},
),
],
),
diff --git a/lib/view/components/kanji/result/yomi_chips.dart b/lib/view/components/kanji/result/yomi_chips.dart
deleted file mode 100644
index 7ee1757..0000000
--- a/lib/view/components/kanji/result/yomi_chips.dart
+++ /dev/null
@@ -1,122 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:jisho_study_tool/bloc/theme/theme_bloc.dart';
-
-enum YomiType {
- onyomi,
- kunyomi,
- meaning,
-}
-
-extension on YomiType {
- String get title {
- switch (this) {
- case YomiType.onyomi:
- return 'Onyomi';
- case YomiType.kunyomi:
- return 'Kunyomi';
- case YomiType.meaning:
- return 'Meanings';
- }
- }
-
- ColorSet getColors(BuildContext context) {
- final theme = BlocProvider.of(context).state.theme;
-
- switch (this) {
- case YomiType.onyomi:
- return theme.onyomiColor;
- case YomiType.kunyomi:
- return theme.kunyomiColor;
- case YomiType.meaning:
- return theme.menuGreyNormal;
- }
- }
-}
-
-class YomiChips extends StatelessWidget {
- final List yomi;
- final YomiType type;
-
- const YomiChips(this.yomi, this.type);
-
- @override
- Widget build(BuildContext context) {
- return Container(
- margin: EdgeInsets.symmetric(
- horizontal: 10.0,
- vertical: 5.0,
- ),
- alignment: Alignment.centerLeft,
- child: _yomiWrapper(context),
- );
- }
-
- bool isExpandable() => yomi.length > 6;
-
- Widget _yomiWrapper(BuildContext context) {
- final yomiCards = this
- .yomi
- .map((yomi) => _YomiCard(
- yomi: yomi,
- colors: this.type.getColors(context),
- ))
- .toList();
-
- if (!this.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),
- ),
- ),
- children: [
- SizedBox(
- height: 20.0,
- ),
- Wrap(
- runSpacing: 10.0,
- children: yomiCards,
- ),
- 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,
- horizontal: 10.0,
- ),
- child: Text(
- this.yomi,
- style: TextStyle(
- fontSize: 20.0,
- color: colors.foreground,
- ),
- ),
- decoration: BoxDecoration(
- color: colors.background,
- borderRadius: BorderRadius.circular(10.0),
- ),
- );
- }
-}
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..66255e6 100644
--- a/lib/view/components/search/language_selector.dart
+++ b/lib/view/components/search/language_selector.dart
@@ -1,59 +1,55 @@
import 'package:flutter/material.dart';
-import 'package:jisho_study_tool/models/themes/theme.dart';
+import 'package:get_it/get_it.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 {
- 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() async {
- await 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() {
- return prefs
+ 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)),
+ );
@override
Widget build(BuildContext context) {
return ToggleButtons(
selectedColor: AppTheme.jishoGreen.background,
isSelected: isSelected,
- children: [
- _LanguageOption("Auto"),
- _LanguageOption("日本語"),
- _LanguageOption("English")
+ children: [
+ _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,19 +57,4 @@ class _LanguageSelectorState extends State {
},
);
}
-
}
-
-class _LanguageOption extends StatelessWidget {
- final String language;
-
- const _LanguageOption(this.language);
-
- @override
- Widget build(BuildContext context) {
- return Container(
- padding: 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 b8d63d2..1a56acf 100644
--- a/lib/view/components/search/search_bar.dart
+++ b/lib/view/components/search/search_bar.dart
@@ -1,22 +1,19 @@
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';
+
+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(
- onSubmitted: (text) {
- BlocProvider.of(context)
- .add(GetSearchResults(text));
- },
+ onSubmitted: (text) =>
+ Navigator.pushNamed(context, '/search', arguments: text),
controller: TextEditingController(),
decoration: InputDecoration(
labelText: 'Search',
@@ -25,12 +22,10 @@ class SearchBar extends StatelessWidget {
),
),
),
- SizedBox(
- height: 10.0,
- ),
- LanguageSelector()
+ const SizedBox(height: 10.0),
+ const LanguageSelector()
],
),
);
}
-}
\ 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..d00c770
--- /dev/null
+++ b/lib/view/components/search/search_result_body.dart
@@ -0,0 +1,20 @@
+import 'package:flutter/material.dart';
+import 'package:unofficial_jisho_api/api.dart';
+
+import 'search_results_body/search_card.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: result)).toList(),
+ );
+ }
+}
diff --git a/lib/view/components/search/search_result_page/parts/common_badge.dart b/lib/view/components/search/search_result_page/parts/common_badge.dart
deleted file mode 100644
index 8bb6acb..0000000
--- a/lib/view/components/search/search_result_page/parts/common_badge.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:jisho_study_tool/view/components/search/search_result_page/parts/badge.dart';
-
-class CommonBadge extends StatelessWidget {
- final bool isCommon;
-
- const CommonBadge(this.isCommon);
-
- @override
- Widget build(BuildContext context) {
- return Badge(
- Text(
- "C",
- style: TextStyle(color: this.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_result_page/parts/jlpt_badge.dart b/lib/view/components/search/search_result_page/parts/jlpt_badge.dart
deleted file mode 100644
index d0566d6..0000000
--- a/lib/view/components/search/search_result_page/parts/jlpt_badge.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:jisho_study_tool/view/components/search/search_result_page/parts/badge.dart';
-
-class JLPTBadge extends StatelessWidget {
- final String jlptLevel;
-
- const JLPTBadge(this.jlptLevel);
-
- String _extractJlptLevel(String jlptRaw) {
- return jlptRaw.isNotEmpty ? jlptRaw.substring(5).toUpperCase() : '';
- }
-
- @override
- Widget build(BuildContext context) {
- return Badge(
- Text(
- _extractJlptLevel(this.jlptLevel),
- style: 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_result_page/parts/senses.dart b/lib/view/components/search/search_result_page/parts/senses.dart
deleted file mode 100644
index 510054d..0000000
--- a/lib/view/components/search/search_result_page/parts/senses.dart
+++ /dev/null
@@ -1,62 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:unofficial_jisho_api/parser.dart';
-
-class Senses extends StatelessWidget {
- final List senses;
-
- const Senses(this.senses);
-
- @override
- Widget build(BuildContext context) {
- final List senseWidgets =
- senses.asMap().entries.map((e) => _Sense(e.key, e.value)).toList();
-
- return Container(
- child: Column(
- children: senseWidgets,
- ));
- }
-}
-
-class _Sense extends StatelessWidget {
- final int index;
- final JishoWordSense sense;
-
- const _Sense(this.index, this.sense);
-
- @override
- Widget build(BuildContext context) {
- return Container(
- child: Column(
- children: [
- Row(
- children: [
- Text(
- (index + 1).toString() + '. ',
- style: TextStyle(color: Colors.grey),
- ),
- Text(
- sense.partsOfSpeech.join(', '),
- style: TextStyle(fontWeight: FontWeight.bold),
- textAlign: TextAlign.left,
- ),
- ],
- ),
- 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_result_page/parts/wanikani_badge.dart b/lib/view/components/search/search_result_page/parts/wanikani_badge.dart
deleted file mode 100644
index a24f9f8..0000000
--- a/lib/view/components/search/search_result_page/parts/wanikani_badge.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:jisho_study_tool/view/components/search/search_result_page/parts/badge.dart';
-
-class WKBadge extends StatelessWidget {
- final String wkLevel;
-
- const WKBadge(this.wkLevel);
-
- String _extractWkLevel(String wkRaw) {
- // return jlptRaw.isNotEmpty ? jlptRaw.substring(5).toUpperCase() : '';
- return wkRaw.isNotEmpty ? 'W' + wkRaw.substring(8) : '';
- }
-
- @override
- Widget build(BuildContext context) {
- return Badge(
- Text(
- _extractWkLevel(this.wkLevel),
- style: TextStyle(
- color: Colors.white,
- ),
- ),
- this.wkLevel.isNotEmpty ? Colors.red : Colors.transparent
- );
- }
-}
\ No newline at end of file
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 59%
rename from lib/view/components/search/search_result_page/parts/badge.dart
rename to lib/view/components/search/search_results_body/parts/badge.dart
index 3ddf3aa..457fc01 100644
--- a/lib/view/components/search/search_result_page/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
new file mode 100644
index 0000000..bdcaad2
--- /dev/null
+++ b/lib/view/components/search/search_results_body/parts/common_badge.dart
@@ -0,0 +1,24 @@
+import 'package:flutter/material.dart';
+import './badge.dart';
+
+class CommonBadge extends StatelessWidget {
+ final bool isCommon;
+
+ const CommonBadge({
+ required this.isCommon,
+ Key? key,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Badge(
+ color: isCommon ? Colors.green : Colors.transparent,
+ child: Text(
+ 'C',
+ style: TextStyle(
+ color: isCommon ? Colors.white : Colors.transparent,
+ ),
+ ),
+ );
+ }
+}
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 53%
rename from lib/view/components/search/search_result_page/parts/header.dart
rename to lib/view/components/search/search_results_body/parts/header.dart
index 677ae37..46eaba4 100644
--- a/lib/view/components/search/search_result_page/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
new file mode 100644
index 0000000..77e97c5
--- /dev/null
+++ b/lib/view/components/search/search_results_body/parts/jlpt_badge.dart
@@ -0,0 +1,25 @@
+import 'package:flutter/material.dart';
+import './badge.dart';
+
+class JLPTBadge extends StatelessWidget {
+ final String jlptLevel;
+
+ const JLPTBadge({
+ required this.jlptLevel,
+ Key? key,
+ }) : super(key: key);
+
+ String get formattedJlptLevel =>
+ jlptLevel.isNotEmpty ? jlptLevel.substring(5).toUpperCase() : '';
+
+ @override
+ Widget build(BuildContext context) {
+ return Badge(
+ color: jlptLevel.isNotEmpty ? Colors.blue : Colors.transparent,
+ child: Text(
+ formattedJlptLevel,
+ style: const TextStyle(color: Colors.white),
+ ),
+ );
+ }
+}
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 54%
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
index 8ea8dc1..d690f8c 100644
--- a/lib/view/components/search/search_result_page/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
new file mode 100644
index 0000000..1bd0ccc
--- /dev/null
+++ b/lib/view/components/search/search_results_body/parts/senses.dart
@@ -0,0 +1,62 @@
+import 'package:flutter/material.dart';
+import 'package:unofficial_jisho_api/parser.dart';
+
+class Senses extends StatelessWidget {
+ final List 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 Column(
+ children: senseWidgets,
+ );
+ }
+}
+
+class _Sense extends StatelessWidget {
+ final int index;
+ final JishoWordSense sense;
+
+ const _Sense(this.index, this.sense);
+
+ @override
+ Widget build(BuildContext context) {
+ 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: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children:
+ sense.englishDefinitions.map((def) => Text(def)).toList(),
+ ),
+ ],
+ ),
+ ),
+ ],
+ );
+ }
+}
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
new file mode 100644
index 0000000..96df9c8
--- /dev/null
+++ b/lib/view/components/search/search_results_body/parts/wanikani_badge.dart
@@ -0,0 +1,28 @@
+import 'package:flutter/material.dart';
+import './badge.dart';
+
+class WKBadge extends StatelessWidget {
+ final String level;
+
+ const WKBadge({
+ required this.level,
+ Key? key,
+ }) : super(key: key);
+
+ String _extractWkLevel(String wkRaw) {
+ return wkRaw.isNotEmpty ? 'W${wkRaw.substring(8)}' : '';
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Badge(
+ color: level.isNotEmpty ? Colors.red : Colors.transparent,
+ child: Text(
+ _extractWkLevel(level),
+ style: const TextStyle(
+ color: Colors.white,
+ ),
+ ),
+ );
+ }
+}
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 56%
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..d4c8129 100644
--- a/lib/view/components/search/search_result_page/search_card.dart
+++ b/lib/view/components/search/search_results_body/search_card.dart
@@ -1,23 +1,24 @@
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;
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) {
@@ -25,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(
+ level: 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/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/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/history.dart b/lib/view/screens/history.dart
index 0a45b19..f413512 100644
--- a/lib/view/screens/history.dart
+++ b/lib/view/screens/history.dart
@@ -1,80 +1,113 @@
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:get_it/get_it.dart';
+import 'package:jisho_study_tool/view/components/common/loading.dart';
+import 'package:sembast/sembast.dart';
-import 'package:jisho_study_tool/objectbox.g.dart';
-import 'package:jisho_study_tool/view/components/opaque_box.dart';
+import '../../models/history/search.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);
+
+ 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: searchStream,
+ builder: (context, snapshot) {
+ if (!snapshot.hasData) return const LoadingScreen();
- 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 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);
+ final List data = snapshot.data!;
+ if (data.isEmpty)
+ return const Center(
+ child: Text('The history is empty.\nTry searching for something!'),
+ );
- 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();
- },
- ),
- );
- },
+ return OpaqueBox(
+ child: ListView.separated(
+ itemCount: data.length + 1,
+ itemBuilder: historyEntryWithData(data),
+ separatorBuilder: historyEntrySeparatorWithData(data),
+ ),
);
},
);
}
+
+ Widget Function(BuildContext, int) historyEntryWithData(List data) =>
+ (context, index) {
+ if (index == 0) return Container();
+
+ final Search search = data[index - 1];
+
+ return (search.isKanji)
+ ? KanjiSearchItem(
+ result: search.kanjiQuery!,
+ timestamp: search.timestamp,
+ )
+ : PhraseSearchItem(
+ search: search.wordQuery!,
+ 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/kanji/result.dart b/lib/view/screens/kanji/result.dart
deleted file mode 100644
index 3e3a754..0000000
--- a/lib/view/screens/kanji/result.dart
+++ /dev/null
@@ -1,98 +0,0 @@
-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';
-
-class KanjiResultCard extends StatelessWidget {
- late final String query;
- late final jisho.KanjiResultData resultData;
-
- KanjiResultCard({required jisho.KanjiResult result}) {
-
- query = result.query;
-
- // TODO: Handle this kind of exception before widget is initialized
- if (result.data == null)
- throw Exception();
-
- resultData = result.data!;
- }
-
- @override
- Widget build(BuildContext context) {
- return ListView(
- children: [
- Container(
- margin: EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 30.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: [
- Flexible(
- flex: 1,
- fit: FlexFit.tight,
- child: Center(child: SizedBox()),
- ),
- Flexible(
- flex: 1,
- fit: FlexFit.tight,
- child: Center(child: Header(query)),
- ),
- Flexible(
- flex: 1,
- fit: FlexFit.tight,
- child: Center(
- child: (resultData.radical != null) ? Radical(resultData.radical!) : 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(),
- 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),
- ],
- ),
- ],
- ),
- ),
- ],
- ),
- ),
- Examples(resultData.onyomiExamples, resultData.kunyomiExamples),
- ],
- );
- }
-}
\ No newline at end of file
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/search/grid.dart b/lib/view/screens/kanji/search/grid.dart
deleted file mode 100644
index 5aaca73..0000000
--- a/lib/view/screens/kanji/search/grid.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-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';
-
-class SearchGrid extends StatelessWidget {
- final List suggestions;
- const SearchGrid(this.suggestions);
-
- @override
- Widget build(BuildContext context) {
- return
- Column(
- children: [
- SizedBox(height: 10),
- KanjiSearchBar(),
- SizedBox(height: 10),
- Expanded(
- child: KanjiGrid(suggestions)
- )
- ],
- );
- }
-}
\ No newline at end of file
diff --git a/lib/view/screens/kanji/search/radical_list.dart b/lib/view/screens/kanji/search/radical_list.dart
deleted file mode 100644
index 8d93387..0000000
--- a/lib/view/screens/kanji/search/radical_list.dart
+++ /dev/null
@@ -1 +0,0 @@
-const List> radicals = [[]];
\ 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..07a6f2b
--- /dev/null
+++ b/lib/view/screens/search/kanji_result_page.dart
@@ -0,0 +1,43 @@
+import 'package:flutter/material.dart';
+import 'package:get_it/get_it.dart';
+import 'package:sembast/sembast.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);
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(),
+ body: FutureBuilder(
+ future: fetchKanji(kanjiSearchTerm),
+ builder: (context, snapshot) {
+ if (!snapshot.hasData) return const LoadingScreen();
+ if (snapshot.hasError) return ErrorWidget(snapshot.error!);
+
+ if (!addedToDatabase) {
+ Search.store.add(
+ GetIt.instance.get(),
+ Search.fromKanjiQuery(
+ timestamp: DateTime.now(),
+ kanjiQuery: KanjiQuery(kanji: kanjiSearchTerm),
+ ).toJson(),
+ );
+ addedToDatabase = true;
+ }
+
+ return KanjiResultBody(result: snapshot.data!);
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/view/screens/search/kanji_view.dart b/lib/view/screens/search/kanji_view.dart
new file mode 100644
index 0000000..77f8042
--- /dev/null
+++ b/lib/view/screens/search/kanji_view.dart
@@ -0,0 +1,13 @@
+
+import 'package:flutter/material.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 const KanjiSearchBody();
+ }
+}
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/search/search_mechanisms/grid.dart b/lib/view/screens/search/search_mechanisms/grid.dart
new file mode 100644
index 0000000..742e0a0
--- /dev/null
+++ b/lib/view/screens/search/search_mechanisms/grid.dart
@@ -0,0 +1,25 @@
+import 'package:flutter/material.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({
+ required this.suggestions,
+ Key? key,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ const SizedBox(height: 10),
+ const KanjiSearchBar(),
+ const SizedBox(height: 10),
+ Expanded(child: KanjiGrid(suggestions: suggestions))
+ ],
+ );
+ }
+}
diff --git a/lib/view/screens/search/search_mechanisms/radical_list.dart b/lib/view/screens/search/search_mechanisms/radical_list.dart
new file mode 100644
index 0000000..a6ed8a2
--- /dev/null
+++ b/lib/view/screens/search/search_mechanisms/radical_list.dart
@@ -0,0 +1 @@
+const List> radicals = [[]];
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..96f779a
--- /dev/null
+++ b/lib/view/screens/search/search_results_page.dart
@@ -0,0 +1,49 @@
+import 'package:flutter/material.dart';
+import 'package:get_it/get_it.dart';
+import 'package:sembast/sembast.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;
+ final Future results;
+ bool addedToDatabase = false;
+
+ SearchResultsPage({required this.searchTerm, Key? key})
+ : 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 const LoadingScreen();
+ if (snapshot.hasError || snapshot.data!.data == null)
+ return ErrorWidget(snapshot.error!);
+
+ if (!addedToDatabase) {
+ Search.store.add(
+ GetIt.instance.get(),
+ Search.fromWordQuery(
+ timestamp: DateTime.now(),
+ wordQuery: WordQuery(query: searchTerm),
+ ).toJson(),
+ );
+ addedToDatabase = true;
+ }
+
+ return SearchResultsBody(
+ results: snapshot.data!.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..d68be17
--- /dev/null
+++ b/lib/view/screens/search/search_view.dart
@@ -0,0 +1,16 @@
+import 'package:flutter/material.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: const [
+ 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/lib/view/screens/settings.dart b/lib/view/screens/settings.dart
index 40d4709..4723513 100644
--- a/lib/view/screens/settings.dart
+++ b/lib/view/screens/settings.dart
@@ -1,22 +1,23 @@
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: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/theme/theme_bloc.dart';
+import '../../models/history/search.dart';
+import '../../models/themes/theme.dart';
+
class SettingsView extends StatefulWidget {
- SettingsView({Key? key}) : super(key: key);
+ const SettingsView({Key? key}) : super(key: key);
@override
_SettingsViewState createState() => _SettingsViewState();
}
class _SettingsViewState extends State {
- late final SharedPreferences prefs;
+ final SharedPreferences prefs = GetIt.instance.get();
bool darkThemeEnabled = false;
bool autoThemeEnabled = false;
@@ -24,41 +25,41 @@ 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
- void _updatePrefs() async {
- await prefs.setBool('darkThemeEnabled', darkThemeEnabled);
- await prefs.setBool('autoThemeEnabled', autoThemeEnabled);
+ 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(
- 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 +75,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 +91,7 @@ class _SettingsViewState extends State {
SettingsSection(
title: 'Cache',
titleTextStyle: _titleTextStyle,
- tiles: [
+ tiles: [
SettingsTile.switchTile(
title: 'Cache grade 1-7 kanji',
switchValue: false,
@@ -123,24 +125,23 @@ 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(
- leading: Icon(Icons.delete),
+ 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: 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,
)
],
@@ -149,13 +150,3 @@ 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();
- }
-}
diff --git a/pubspec.lock b/pubspec.lock
index 62ace01..5161dd6 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -7,35 +7,49 @@ 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: "3.0.0"
+ archive:
+ dependency: transitive
+ description:
+ name: archive
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.1.6"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.1"
+ version: "2.3.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.7.0"
+ version: "2.8.1"
bloc:
dependency: transitive
description:
name: bloc
url: "https://pub.dartlang.org"
source: hosted
- version: "7.0.0"
+ version: "8.0.1"
boolean_selector:
dependency: transitive
description:
@@ -49,56 +63,56 @@ packages:
name: build
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.3"
+ version: "2.1.1"
build_config:
dependency: transitive
description:
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.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: "1.12.2"
+ version: "2.1.5"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
- version: "6.1.12"
+ 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:
@@ -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:
@@ -126,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:
@@ -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,21 +189,21 @@ packages:
name: csslib
url: "https://pub.dartlang.org"
source: hosted
- version: "0.16.2"
+ 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:
name: division
url: "https://pub.dartlang.org"
source: hosted
- version: "0.8.8"
+ version: "0.9.0"
fake_async:
dependency: transitive
description:
@@ -196,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:
@@ -222,7 +243,28 @@ packages:
name: flutter_bloc
url: "https://pub.dartlang.org"
source: hosted
- version: "7.0.0"
+ version: "8.0.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.3.2"
+ flutter_slidable:
+ dependency: "direct main"
+ description:
+ name: flutter_slidable
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -233,41 +275,55 @@ 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"
+ get_it:
+ dependency: "direct main"
+ description:
+ name: get_it
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "7.2.0"
glob:
dependency: transitive
description:
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: "1.0.0"
+ version: "2.1.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.4"
http_multi_server:
dependency: transitive
description:
@@ -281,7 +337,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.1.0"
io:
dependency: transitive
description:
@@ -302,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:
@@ -323,21 +386,21 @@ packages:
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:
name: mime
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.0"
+ version: "1.0.1"
nested:
dependency: transitive
description:
@@ -345,36 +408,15 @@ 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:
name: package_config
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.0"
+ version: "2.0.2"
path:
- dependency: transitive
+ dependency: "direct main"
description:
name: path
url: "https://pub.dartlang.org"
@@ -386,56 +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:
+ version: "2.0.4"
+ petitparser:
dependency: transitive
description:
- name: pedantic
+ name: petitparser
url: "https://pub.dartlang.org"
source: hosted
- version: "1.11.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: "1.0.3"
+ version: "2.0.2"
pool:
dependency: transitive
description:
@@ -449,27 +505,41 @@ 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: "5.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.1.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:
+ name: settings_ui
+ url: "https://pub.dartlang.org"
+ source: hosted
version: "1.0.0"
shared_preferences:
dependency: "direct main"
@@ -477,21 +547,35 @@ packages:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
- version: "2.0.5"
+ 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:
@@ -505,40 +589,33 @@ 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:
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
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:
@@ -574,6 +651,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:
@@ -587,7 +671,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.4.0"
+ version: "0.4.2"
timing:
dependency: transitive
description:
@@ -602,55 +686,76 @@ 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.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:
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:
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:
@@ -664,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:
@@ -678,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:
@@ -686,6 +791,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.3.1"
yaml:
dependency: transitive
description:
@@ -694,5 +806,5 @@ packages:
source: hosted
version: "3.1.0"
sdks:
- dart: ">=2.12.0 <3.0.0"
- flutter: ">=2.0.0"
+ dart: ">=2.14.0 <3.0.0"
+ flutter: ">=2.5.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 53933ed..023e5d0 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -6,28 +6,27 @@ 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
- 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"
@@ -41,6 +40,7 @@ flutter:
assets:
- assets/images/denshi_jisho_background_overlay.png
+ - assets/images/logo/
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
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);
- });
-}