├── .gitignore ├── CHANGELOG.md ├── LICENSE.txt ├── PRIVACY_POLICY.md ├── README.md ├── screenshots ├── dark.png ├── dark │ ├── 01-splash_screen.jpg │ ├── 02-latest.jpg │ ├── 03-latest_scrolled.jpg │ ├── 04-tournament.jpg │ ├── 05-tournament_menu.jpg │ ├── 06-tournament_about.jpg │ ├── 07-tournaments_tree.jpg │ ├── 08-search.jpg │ ├── 09-settings.jpg │ ├── 10-question1.jpg │ ├── 11-question2.jpg │ ├── 12-search2.jpg │ ├── 13-tournament2.jpg │ ├── 14-question3.jpg │ ├── 15-about.jpg │ ├── 16-tournaments_tree2.jpg │ └── 17-tournaments_tree3.jpg ├── dark_minimized.png ├── light.png ├── light │ ├── 01-splash_screen.jpg │ ├── 02-latest.jpg │ ├── 03-latest_scrolled.jpg │ ├── 04-tournament.jpg │ ├── 05-tournament_menu.jpg │ ├── 06-tournament_about.jpg │ ├── 07-tournaments_tree.jpg │ ├── 08-search.jpg │ ├── 09-settings.jpg │ ├── 10-question1.jpg │ ├── 11-question2.jpg │ ├── 12-search2.jpg │ ├── 13-tournament2.jpg │ ├── 14-question3.jpg │ ├── 15-about.jpg │ ├── 16-tournaments_tree2.jpg │ └── 17-tournaments_tree3.jpg └── light_minimized.png └── www-app ├── .gitignore ├── app ├── www_app │ ├── .gitignore │ ├── .metadata │ ├── analysis_options.yaml │ ├── android │ │ ├── .gitignore │ │ ├── app │ │ │ ├── build.gradle │ │ │ ├── google-services.json │ │ │ └── src │ │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ │ ├── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── droid │ │ │ │ │ │ └── chgk │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── res │ │ │ │ │ ├── drawable │ │ │ │ │ ├── launcher_icon_background.xml │ │ │ │ │ ├── launcher_icon_foreground.xml │ │ │ │ │ └── screen_background.xml │ │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ │ └── launcher_icon.xml │ │ │ │ │ ├── values-night │ │ │ │ │ ├── colors.xml │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── values-ru │ │ │ │ │ └── strings.xml │ │ │ │ │ ├── values-uk │ │ │ │ │ └── strings.xml │ │ │ │ │ └── values │ │ │ │ │ ├── colors.xml │ │ │ │ │ ├── strings.xml │ │ │ │ │ └── styles.xml │ │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ └── gradle-wrapper.properties │ │ └── settings.gradle │ ├── assets │ │ ├── owl.svg │ │ └── timer.mp3 │ ├── ios │ │ ├── .gitignore │ │ ├── Flutter │ │ │ ├── AppFrameworkInfo.plist │ │ │ ├── Debug.xcconfig │ │ │ └── Release.xcconfig │ │ ├── Runner.xcodeproj │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ ├── Runner.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── Runner │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ └── LaunchImage.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ └── README.md │ │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ │ ├── GoogleService-Info.plist │ │ │ ├── Info.plist │ │ │ ├── Runner-Bridging-Header.h │ │ │ ├── en.lproj │ │ │ └── InfoPlist.strings │ │ │ ├── ru.lproj │ │ │ └── InfoPlist.strings │ │ │ └── uk.lproj │ │ │ └── InfoPlist.strings │ ├── lib │ │ ├── main.dart │ │ └── src │ │ │ ├── app.dart │ │ │ └── presentation │ │ │ └── splash_screen.dart │ ├── pubspec.lock │ └── pubspec.yaml ├── www_app_di │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ └── di │ │ │ │ ├── di_container.dart │ │ │ │ ├── di_container_implementation.dart │ │ │ │ └── di_module.dart │ │ └── www_app_di.dart │ └── pubspec.yaml ├── www_navigation │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── redux │ │ │ │ └── middleware.dart │ │ │ └── service │ │ │ │ └── navigation.dart │ │ └── www_navigation.dart │ └── pubspec.yaml └── www_redux_store │ ├── analysis_options.yaml │ ├── lib │ ├── src │ │ ├── di │ │ │ ├── di_module.config.dart │ │ │ └── di_module.dart │ │ ├── loggers │ │ │ ├── analytics │ │ │ │ └── middleware.dart │ │ │ └── logs │ │ │ │ └── middleware.dart │ │ └── redux │ │ │ ├── middleware.dart │ │ │ ├── reducer.dart │ │ │ ├── state.dart │ │ │ ├── state.freezed.dart │ │ │ └── store.dart │ └── www_redux_store.dart │ ├── pubspec.yaml │ └── test │ ├── loggers │ └── analytics │ │ └── middleware_test.dart │ └── mocks │ ├── fakes.dart │ └── mocks.dart ├── core ├── www_constants │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ └── constants.dart │ │ └── www_constants.dart │ └── pubspec.yaml ├── www_http │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── dio │ │ │ │ ├── dio_config │ │ │ │ │ ├── dio_config_module.dart │ │ │ │ │ └── dio_config_parameters.dart │ │ │ │ ├── dio_factory.dart │ │ │ │ └── dio_logger.dart │ │ │ └── service │ │ │ │ └── http_client.dart │ │ └── www_http.dart │ └── pubspec.yaml └── www_localization │ ├── analysis_options.yaml │ ├── lib │ ├── src │ │ ├── extensions.dart │ │ ├── localizations.dart │ │ └── translations │ │ │ ├── translations.i69n.dart │ │ │ ├── translations.i69n.yaml │ │ │ ├── translations_ru.i69n.dart │ │ │ ├── translations_ru.i69n.yaml │ │ │ ├── translations_uk.i69n.dart │ │ │ └── translations_uk.i69n.yaml │ └── www_localization.dart │ └── pubspec.yaml ├── design ├── www_custom_icons │ ├── analysis_options.yaml │ ├── assets │ │ └── CustomIcons.ttf │ ├── lib │ │ ├── src │ │ │ └── custom_icons.dart │ │ └── www_custom_icons.dart │ └── pubspec.yaml ├── www_theme │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── dimensions.dart │ │ │ ├── extensions.dart │ │ │ ├── style_configuration.dart │ │ │ ├── style_configurator.dart │ │ │ ├── text_sections_theme_data.dart │ │ │ └── themes.dart │ │ └── www_theme.dart │ └── pubspec.yaml └── www_widgets │ ├── analysis_options.yaml │ ├── lib │ ├── src │ │ ├── animated_fab.dart │ │ ├── bookmarked_marker.dart │ │ ├── empty_sliver.dart │ │ ├── error_message.dart │ │ ├── expanding_panel.dart │ │ ├── fade_in.dart │ │ ├── gradient_decoration.dart │ │ ├── info_dialog.dart │ │ ├── modal_bottom_sheet_container.dart │ │ ├── progress_indicator.dart │ │ ├── scroll_controller_bound_fab.dart │ │ ├── shape_hero.dart │ │ ├── solid_icon_button.dart │ │ ├── status_bar_brightness.dart │ │ ├── text_hero.dart │ │ ├── text_stub.dart │ │ ├── tournaments_grid.dart │ │ ├── tournaments_grid_stub_tile.dart │ │ ├── tournaments_grid_tile.dart │ │ └── unexpected_state_widget.dart │ └── www_widgets.dart │ └── pubspec.yaml ├── domain ├── www_api │ ├── analysis_options.yaml │ ├── build.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── loaders │ │ │ │ ├── latest_tournaments_loader.dart │ │ │ │ ├── random_questions_loader.dart │ │ │ │ ├── search_loader.dart │ │ │ │ ├── tour_details_loader.dart │ │ │ │ ├── tournament_details_loader.dart │ │ │ │ └── tournaments_tree_loader.dart │ │ │ ├── models │ │ │ │ ├── json_converters │ │ │ │ │ ├── questions_list_converter.dart │ │ │ │ │ ├── tournaments_tree_converter.dart │ │ │ │ │ └── tours_list_converter.dart │ │ │ │ ├── latest_tournaments_dto.dart │ │ │ │ ├── latest_tournaments_dto.freezed.dart │ │ │ │ ├── latest_tournaments_dto.g.dart │ │ │ │ ├── model_converters │ │ │ │ │ ├── question_converter.dart │ │ │ │ │ ├── question_parser │ │ │ │ │ │ ├── question_parser.dart │ │ │ │ │ │ ├── question_parser_helper.dart │ │ │ │ │ │ └── question_section_type.dart │ │ │ │ │ ├── question_section_converter.dart │ │ │ │ │ ├── random_questions_converter.dart │ │ │ │ │ ├── tour_converter.dart │ │ │ │ │ ├── tournament_converter.dart │ │ │ │ │ └── tournament_tree_converter.dart │ │ │ │ ├── question_dto.dart │ │ │ │ ├── question_dto.freezed.dart │ │ │ │ ├── question_dto.g.dart │ │ │ │ ├── random_questions_dto.dart │ │ │ │ ├── random_questions_dto.freezed.dart │ │ │ │ ├── random_questions_dto.g.dart │ │ │ │ ├── search_tournaments_dto.dart │ │ │ │ ├── search_tournaments_dto.freezed.dart │ │ │ │ ├── search_tournaments_dto.g.dart │ │ │ │ ├── tour_dto.dart │ │ │ │ ├── tour_dto.freezed.dart │ │ │ │ ├── tour_dto.g.dart │ │ │ │ ├── tournament_dto.dart │ │ │ │ ├── tournament_dto.freezed.dart │ │ │ │ ├── tournament_dto.g.dart │ │ │ │ ├── tournaments_tree_dto.dart │ │ │ │ ├── tournaments_tree_dto.freezed.dart │ │ │ │ └── tournaments_tree_dto.g.dart │ │ │ └── parsers │ │ │ │ ├── latest2json_parser.dart │ │ │ │ ├── search2json_parser.dart │ │ │ │ └── xml2json_parser.dart │ │ └── www_api.dart │ ├── pubspec.yaml │ └── test │ │ ├── loaders │ │ ├── latest_tournaments │ │ │ ├── latest_tournaments_loader_test.dart │ │ │ ├── test_data_1.dart │ │ │ └── test_data_2.dart │ │ ├── random_questions │ │ │ ├── random_questions_loader_test.dart │ │ │ ├── test_data_1.dart │ │ │ ├── test_data_2.dart │ │ │ └── test_data_3.dart │ │ ├── search │ │ │ ├── search_loader_test.dart │ │ │ ├── test_data_1.dart │ │ │ ├── test_data_2.dart │ │ │ ├── test_data_3.dart │ │ │ └── test_data_4.dart │ │ ├── tour_details │ │ │ ├── test_data_1.dart │ │ │ ├── test_data_2.dart │ │ │ ├── test_data_3.dart │ │ │ └── tour_details_loader_test.dart │ │ ├── tournament_details │ │ │ ├── test_data_1.dart │ │ │ ├── test_data_2.dart │ │ │ ├── test_data_3.dart │ │ │ └── tournament_details_loader_test.dart │ │ └── tournaments_tree │ │ │ ├── test_data_1.dart │ │ │ └── tournaments_tree_loader_test.dart │ │ ├── mocks │ │ ├── fakes.dart │ │ └── mocks.dart │ │ └── models │ │ └── question_dto_test.dart ├── www_cache │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── cache │ │ │ │ ├── cache_synchronizer.dart │ │ │ │ ├── tournaments_cache.dart │ │ │ │ ├── tournaments_tree_cache.dart │ │ │ │ └── tours_cache.dart │ │ │ └── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ └── www_cache.dart │ └── pubspec.yaml ├── www_local_storage │ ├── analysis_options.yaml │ ├── build.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── hive │ │ │ │ ├── hive_adapters_registry.dart │ │ │ │ ├── hive_constants.dart │ │ │ │ ├── model_converters │ │ │ │ │ ├── question_converter.dart │ │ │ │ │ ├── question_info_converter.dart │ │ │ │ │ ├── question_section_converter.dart │ │ │ │ │ ├── tour_converter.dart │ │ │ │ │ ├── tour_info_converter.dart │ │ │ │ │ ├── tournament_converter.dart │ │ │ │ │ ├── tournament_info_converter.dart │ │ │ │ │ └── tournament_status_converter.dart │ │ │ │ └── models │ │ │ │ │ ├── question.dart │ │ │ │ │ ├── question.freezed.dart │ │ │ │ │ ├── question.g.dart │ │ │ │ │ ├── question_info.dart │ │ │ │ │ ├── question_info.freezed.dart │ │ │ │ │ ├── question_info.g.dart │ │ │ │ │ ├── question_sections │ │ │ │ │ ├── question_section.dart │ │ │ │ │ ├── section_audio.dart │ │ │ │ │ ├── section_audio.freezed.dart │ │ │ │ │ ├── section_audio.g.dart │ │ │ │ │ ├── section_giveaway.dart │ │ │ │ │ ├── section_giveaway.freezed.dart │ │ │ │ │ ├── section_giveaway.g.dart │ │ │ │ │ ├── section_image.dart │ │ │ │ │ ├── section_image.freezed.dart │ │ │ │ │ ├── section_image.g.dart │ │ │ │ │ ├── section_speaker_note.dart │ │ │ │ │ ├── section_speaker_note.freezed.dart │ │ │ │ │ ├── section_speaker_note.g.dart │ │ │ │ │ ├── section_text.dart │ │ │ │ │ ├── section_text.freezed.dart │ │ │ │ │ └── section_text.g.dart │ │ │ │ │ ├── tour.dart │ │ │ │ │ ├── tour.freezed.dart │ │ │ │ │ ├── tour.g.dart │ │ │ │ │ ├── tour_info.dart │ │ │ │ │ ├── tour_info.freezed.dart │ │ │ │ │ ├── tour_info.g.dart │ │ │ │ │ ├── tournament.dart │ │ │ │ │ ├── tournament.freezed.dart │ │ │ │ │ ├── tournament.g.dart │ │ │ │ │ ├── tournament_info.dart │ │ │ │ │ ├── tournament_info.freezed.dart │ │ │ │ │ ├── tournament_info.g.dart │ │ │ │ │ ├── tournament_status.dart │ │ │ │ │ ├── tournament_status.freezed.dart │ │ │ │ │ └── tournament_status.g.dart │ │ │ └── service │ │ │ │ ├── local_storage.dart │ │ │ │ └── tournaments_local_storage.dart │ │ └── www_local_storage.dart │ └── pubspec.yaml └── www_models │ ├── analysis_options.yaml │ ├── lib │ ├── src │ │ ├── misc │ │ │ ├── app_theme.dart │ │ │ ├── search_parameters.dart │ │ │ ├── search_parameters.freezed.dart │ │ │ ├── sorting.dart │ │ │ ├── text_scale.dart │ │ │ └── timer_type.dart │ │ └── models │ │ │ ├── question.dart │ │ │ ├── question.freezed.dart │ │ │ ├── question_info.dart │ │ │ ├── question_info.freezed.dart │ │ │ ├── question_sections │ │ │ ├── question_section.dart │ │ │ ├── section_audio.dart │ │ │ ├── section_audio.freezed.dart │ │ │ ├── section_giveaway.dart │ │ │ ├── section_giveaway.freezed.dart │ │ │ ├── section_image.dart │ │ │ ├── section_image.freezed.dart │ │ │ ├── section_speaker_note.dart │ │ │ ├── section_speaker_note.freezed.dart │ │ │ ├── section_text.dart │ │ │ └── section_text.freezed.dart │ │ │ ├── random_questions.dart │ │ │ ├── random_questions.freezed.dart │ │ │ ├── tour.dart │ │ │ ├── tour.freezed.dart │ │ │ ├── tour_info.dart │ │ │ ├── tour_info.freezed.dart │ │ │ ├── tournament.dart │ │ │ ├── tournament.freezed.dart │ │ │ ├── tournament_info.dart │ │ │ ├── tournament_info.freezed.dart │ │ │ ├── tournament_status.dart │ │ │ ├── tournament_status.freezed.dart │ │ │ ├── tournaments_tree.dart │ │ │ ├── tournaments_tree.freezed.dart │ │ │ ├── tournaments_tree_info.dart │ │ │ └── tournaments_tree_info.freezed.dart │ └── www_models.dart │ └── pubspec.yaml ├── feature ├── shared │ ├── www_redux_actions │ │ ├── analysis_options.yaml │ │ ├── lib │ │ │ ├── src │ │ │ │ ├── bookmarks_actions.dart │ │ │ │ ├── bookmarks_actions.freezed.dart │ │ │ │ ├── browse_actions.dart │ │ │ │ ├── browse_actions.freezed.dart │ │ │ │ ├── developer_actions.dart │ │ │ │ ├── developer_actions.freezed.dart │ │ │ │ ├── dialogs_actions.dart │ │ │ │ ├── dialogs_actions.freezed.dart │ │ │ │ ├── initialization_actions.dart │ │ │ │ ├── initialization_actions.freezed.dart │ │ │ │ ├── latest_tournaments_actions.dart │ │ │ │ ├── latest_tournaments_actions.freezed.dart │ │ │ │ ├── navigation_actions.dart │ │ │ │ ├── navigation_actions.freezed.dart │ │ │ │ ├── questions_actions.dart │ │ │ │ ├── questions_actions.freezed.dart │ │ │ │ ├── rating_actions.dart │ │ │ │ ├── rating_actions.freezed.dart │ │ │ │ ├── services_actions.dart │ │ │ │ ├── services_actions.freezed.dart │ │ │ │ ├── settings_actions.dart │ │ │ │ ├── settings_actions.freezed.dart │ │ │ │ ├── sharing_actions.dart │ │ │ │ ├── sharing_actions.freezed.dart │ │ │ │ ├── timer_actions.dart │ │ │ │ ├── timer_actions.freezed.dart │ │ │ │ ├── tournament_actions.dart │ │ │ │ ├── tournament_actions.freezed.dart │ │ │ │ ├── tournaments_search_actions.dart │ │ │ │ ├── tournaments_search_actions.freezed.dart │ │ │ │ ├── tournaments_tree_actions.dart │ │ │ │ ├── tournaments_tree_actions.freezed.dart │ │ │ │ ├── tours_actions.dart │ │ │ │ └── tours_actions.freezed.dart │ │ │ └── www_redux_actions.dart │ │ └── pubspec.yaml │ └── www_tournament_status │ │ ├── analysis_options.yaml │ │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ └── service │ │ │ │ ├── tournament_status.dart │ │ │ │ ├── tournaments_bookmarks.dart │ │ │ │ └── tournaments_history.dart │ │ └── www_tournament_status.dart │ │ └── pubspec.yaml ├── www_about │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ └── presentation │ │ │ │ └── route_page.dart │ │ └── www_about.dart │ └── pubspec.yaml ├── www_bookmarks │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── presentation │ │ │ │ ├── app_bar.dart │ │ │ │ ├── data_page.dart │ │ │ │ ├── empty_bookmarks.dart │ │ │ │ ├── error_page.dart │ │ │ │ ├── loading_page.dart │ │ │ │ ├── page_content.dart │ │ │ │ └── route_page.dart │ │ │ └── redux │ │ │ │ ├── middleware.dart │ │ │ │ ├── reducer.dart │ │ │ │ ├── state.dart │ │ │ │ ├── state.freezed.dart │ │ │ │ └── state_holder.dart │ │ └── www_bookmarks.dart │ └── pubspec.yaml ├── www_browsing │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── redux │ │ │ │ └── middleware.dart │ │ │ └── service │ │ │ │ └── url_launcher.dart │ │ └── www_browsing.dart │ └── pubspec.yaml ├── www_image_details │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ └── presentation │ │ │ │ └── route_page.dart │ │ └── www_image_details.dart │ └── pubspec.yaml ├── www_initialization │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ └── redux │ │ │ │ ├── middleware.dart │ │ │ │ ├── reducer.dart │ │ │ │ ├── state.dart │ │ │ │ ├── state.freezed.dart │ │ │ │ └── state_holder.dart │ │ └── www_initialization.dart │ └── pubspec.yaml ├── www_latest_tournaments │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── presentation │ │ │ │ ├── app_bar.dart │ │ │ │ ├── app_bar_buttons │ │ │ │ │ ├── bookmarks.dart │ │ │ │ │ ├── more.dart │ │ │ │ │ └── random.dart │ │ │ │ ├── bottom_sheet │ │ │ │ │ ├── bottom_sheet.dart │ │ │ │ │ └── items │ │ │ │ │ │ ├── about.dart │ │ │ │ │ │ ├── search.dart │ │ │ │ │ │ ├── settings.dart │ │ │ │ │ │ └── tree.dart │ │ │ │ ├── data_page.dart │ │ │ │ ├── error_message.dart │ │ │ │ ├── error_page.dart │ │ │ │ ├── loading_page.dart │ │ │ │ ├── page_content.dart │ │ │ │ ├── refresh_indicator.dart │ │ │ │ └── route_page.dart │ │ │ ├── redux │ │ │ │ ├── middleware.dart │ │ │ │ ├── reducer.dart │ │ │ │ ├── state.dart │ │ │ │ ├── state.freezed.dart │ │ │ │ └── state_holder.dart │ │ │ └── service │ │ │ │ └── latest_tournaments_provider.dart │ │ └── www_latest_tournaments.dart │ ├── pubspec.yaml │ └── test │ │ ├── mocks │ │ └── mocks.dart │ │ └── service │ │ └── latest_tournaments_provider │ │ ├── latest_tournaments_provider_test.dart │ │ └── test_data_1.dart ├── www_questions │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── presentation │ │ │ │ ├── app_bar │ │ │ │ │ ├── bottom_app_bar.dart │ │ │ │ │ ├── buttons │ │ │ │ │ │ ├── more.dart │ │ │ │ │ │ └── timer.dart │ │ │ │ │ └── timer_text.dart │ │ │ │ ├── bottom_sheet │ │ │ │ │ ├── bottom_sheet.dart │ │ │ │ │ └── items │ │ │ │ │ │ ├── about.dart │ │ │ │ │ │ ├── browse.dart │ │ │ │ │ │ └── share.dart │ │ │ │ ├── data_page.dart │ │ │ │ ├── error_page.dart │ │ │ │ ├── loading_page.dart │ │ │ │ ├── page_content.dart │ │ │ │ ├── question │ │ │ │ │ ├── question_answer.dart │ │ │ │ │ ├── question_card.dart │ │ │ │ │ ├── question_card_stub.dart │ │ │ │ │ ├── question_number.dart │ │ │ │ │ ├── question_sections.dart │ │ │ │ │ ├── question_text.dart │ │ │ │ │ ├── separator.dart │ │ │ │ │ ├── show_answer_button.dart │ │ │ │ │ └── text_with_links.dart │ │ │ │ ├── questions_cards.dart │ │ │ │ ├── route_page.dart │ │ │ │ └── tour_details_about_dialog.dart │ │ │ ├── redux │ │ │ │ ├── middleware.dart │ │ │ │ ├── reducer.dart │ │ │ │ ├── state.dart │ │ │ │ ├── state.freezed.dart │ │ │ │ └── state_holder.dart │ │ │ └── service │ │ │ │ └── random_questions_provider.dart │ │ └── www_questions.dart │ ├── pubspec.yaml │ └── test │ │ ├── mocks │ │ └── mocks.dart │ │ └── service │ │ ├── random_questions_provider_test.dart │ │ └── test_data_1.dart ├── www_rating │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── presentation │ │ │ │ └── rating_dialog.dart │ │ │ ├── redux │ │ │ │ └── middleware.dart │ │ │ └── service │ │ │ │ └── rating.dart │ │ └── www_rating.dart │ └── pubspec.yaml ├── www_settings │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── presentation │ │ │ │ ├── expiring_timer_settings.dart │ │ │ │ ├── route_page.dart │ │ │ │ ├── text_scale_settings.dart │ │ │ │ └── theme_settings.dart │ │ │ └── redux │ │ │ │ ├── middleware.dart │ │ │ │ ├── reducer.dart │ │ │ │ ├── state.dart │ │ │ │ ├── state.freezed.dart │ │ │ │ └── state_holder.dart │ │ └── www_settings.dart │ └── pubspec.yaml ├── www_sharing │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── redux │ │ │ │ └── middleware.dart │ │ │ └── service │ │ │ │ └── sharing.dart │ │ └── www_sharing.dart │ └── pubspec.yaml ├── www_timer │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── redux │ │ │ │ ├── middleware.dart │ │ │ │ ├── reducer.dart │ │ │ │ ├── state.dart │ │ │ │ ├── state.freezed.dart │ │ │ │ └── state_holder.dart │ │ │ ├── service │ │ │ │ ├── sound.dart │ │ │ │ └── vibrating.dart │ │ │ └── utils │ │ │ │ └── timer.dart │ │ └── www_timer.dart │ └── pubspec.yaml ├── www_tournament_details │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── presentation │ │ │ │ ├── about_dialog.dart │ │ │ │ ├── app_bar.dart │ │ │ │ ├── app_bar_buttons │ │ │ │ │ └── more.dart │ │ │ │ ├── bottom_sheet │ │ │ │ │ ├── bottom_sheet.dart │ │ │ │ │ └── items │ │ │ │ │ │ ├── about.dart │ │ │ │ │ │ ├── bookmark.dart │ │ │ │ │ │ ├── browse.dart │ │ │ │ │ │ └── share.dart │ │ │ │ ├── data_page.dart │ │ │ │ ├── error_page.dart │ │ │ │ ├── loading_page.dart │ │ │ │ ├── page_content.dart │ │ │ │ └── route_page.dart │ │ │ ├── redux │ │ │ │ ├── middleware.dart │ │ │ │ ├── reducer.dart │ │ │ │ ├── state.dart │ │ │ │ ├── state.freezed.dart │ │ │ │ └── state_holder.dart │ │ │ ├── service │ │ │ │ └── tournament_details_provider.dart │ │ │ └── utils │ │ │ │ └── measure_text.dart │ │ └── www_tournament_details.dart │ ├── pubspec.yaml │ └── test │ │ ├── mocks │ │ └── mocks.dart │ │ └── service │ │ ├── test_data_1.dart │ │ ├── test_data_2.dart │ │ └── tournament_details_provider_test.dart ├── www_tournament_tours │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── presentation │ │ │ │ ├── data_tile.dart │ │ │ │ ├── error_tile.dart │ │ │ │ ├── loading_tile.dart │ │ │ │ ├── question_data_tile.dart │ │ │ │ ├── question_loading_tile.dart │ │ │ │ ├── question_template_tile.dart │ │ │ │ ├── route_tile.dart │ │ │ │ ├── stub_tile.dart │ │ │ │ └── template_tile.dart │ │ │ ├── redux │ │ │ │ ├── middleware.dart │ │ │ │ ├── reducer.dart │ │ │ │ ├── state.dart │ │ │ │ ├── state.freezed.dart │ │ │ │ └── state_holder.dart │ │ │ └── service │ │ │ │ └── tour_details_provider.dart │ │ └── www_tournament_tours.dart │ ├── pubspec.yaml │ └── test │ │ ├── mocks │ │ └── mocks.dart │ │ └── service │ │ └── tour_details_provider │ │ ├── test_data_1.dart │ │ └── tour_details_provider_test.dart ├── www_tournaments_search │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── di │ │ │ │ ├── di_module.config.dart │ │ │ │ └── di_module.dart │ │ │ ├── presentation │ │ │ │ ├── app_bar │ │ │ │ │ ├── app_bar.dart │ │ │ │ │ └── buttons │ │ │ │ │ │ └── sorting.dart │ │ │ │ ├── data_page.dart │ │ │ │ ├── empty_page.dart │ │ │ │ ├── error_message.dart │ │ │ │ ├── error_page.dart │ │ │ │ ├── loading_page.dart │ │ │ │ ├── page_content.dart │ │ │ │ └── route_page.dart │ │ │ ├── redux │ │ │ │ ├── middleware.dart │ │ │ │ ├── reducer.dart │ │ │ │ ├── state.dart │ │ │ │ ├── state.freezed.dart │ │ │ │ └── state_holder.dart │ │ │ └── service │ │ │ │ └── search_provider.dart │ │ └── www_tournaments_search.dart │ ├── pubspec.yaml │ └── test │ │ ├── mocks │ │ └── mocks.dart │ │ └── service │ │ └── search_provider │ │ ├── search_loader_test.dart │ │ └── test_data_1.dart └── www_tournaments_tree │ ├── analysis_options.yaml │ ├── lib │ ├── src │ │ ├── di │ │ │ ├── di_module.config.dart │ │ │ └── di_module.dart │ │ ├── presentation │ │ │ ├── app_bar.dart │ │ │ ├── data_page.dart │ │ │ ├── error_page.dart │ │ │ ├── loading_page.dart │ │ │ ├── page_content.dart │ │ │ ├── route_page.dart │ │ │ └── subtree_tile.dart │ │ ├── redux │ │ │ ├── middleware.dart │ │ │ ├── reducer.dart │ │ │ ├── state.dart │ │ │ ├── state.freezed.dart │ │ │ └── state_holder.dart │ │ └── service │ │ │ └── tournaments_tree_provider.dart │ └── www_tournaments_tree.dart │ ├── pubspec.yaml │ └── test │ ├── mocks │ └── mocks.dart │ └── service │ └── tournaments_tree_provider │ ├── test_data_1.dart │ └── tournaments_tree_provider_test.dart ├── melos.yaml ├── pubspec.lock ├── pubspec.yaml └── utils ├── www_analysis ├── lib │ └── analysis_options.yaml └── pubspec.yaml ├── www_analytics ├── analysis_options.yaml ├── lib │ ├── src │ │ ├── config │ │ │ ├── firebase_config_module.dart │ │ │ └── firebase_config_parameters.dart │ │ ├── di │ │ │ ├── di_module.config.dart │ │ │ └── di_module.dart │ │ └── service │ │ │ ├── analytics.dart │ │ │ ├── crash_wrapper.dart │ │ │ ├── crashes.dart │ │ │ └── firebase.dart │ └── www_analytics.dart └── pubspec.yaml ├── www_background_runner ├── analysis_options.yaml ├── lib │ ├── src │ │ ├── di │ │ │ ├── di_module.config.dart │ │ │ └── di_module.dart │ │ └── service │ │ │ └── background_runner.dart │ └── www_background_runner.dart └── pubspec.yaml ├── www_di ├── analysis_options.yaml ├── lib │ ├── src │ │ └── di_module.dart │ └── www_di.dart └── pubspec.yaml ├── www_dialogs ├── analysis_options.yaml ├── lib │ ├── src │ │ ├── di │ │ │ ├── di_module.config.dart │ │ │ └── di_module.dart │ │ ├── presentation │ │ │ └── dialog_presenter.dart │ │ └── service │ │ │ └── dialogs.dart │ └── www_dialogs.dart └── pubspec.yaml ├── www_logger ├── analysis_options.yaml ├── lib │ ├── src │ │ └── logger.dart │ └── www_logger.dart └── pubspec.yaml ├── www_preferences ├── analysis_options.yaml ├── lib │ ├── src │ │ ├── di │ │ │ ├── di_module.config.dart │ │ │ └── di_module.dart │ │ └── service │ │ │ └── preferences.dart │ └── www_preferences.dart └── pubspec.yaml ├── www_redux ├── analysis_options.yaml ├── lib │ ├── src │ │ ├── extensions │ │ │ └── context_extensions.dart │ │ ├── presentation │ │ │ ├── store_connector.dart │ │ │ └── store_provider.dart │ │ └── redux │ │ │ ├── action.dart │ │ │ ├── middleware.dart │ │ │ ├── reducer.dart │ │ │ └── state.dart │ └── www_redux.dart └── pubspec.yaml ├── www_test_utils ├── analysis_options.yaml ├── lib │ ├── src │ │ ├── test_arrange.dart │ │ └── test_assert.dart │ └── www_test_utils.dart └── pubspec.yaml └── www_utils ├── analysis_options.yaml ├── lib ├── src │ ├── duration_formatter.dart │ ├── extensions │ │ ├── iterable_extensions.dart │ │ └── string_extensions.dart │ ├── network_exception.dart │ ├── silent_operation.dart │ └── uri_detector.dart └── www_utils.dart └── pubspec.yaml /PRIVACY_POLICY.md: -------------------------------------------------------------------------------- 1 | # "Sova – What? Where? When?" mobile app Privacy Policy 2 | 3 | "Sova – What? Where? When?" is a free mobile application created by [Anna Leushchenko](https://github.com/foxanna). The source code is openly available [on GitHub](https://github.com/foxanna/WWW-flutter) and the application is available on [Google Play](https://play.google.com/store/apps/details?id=chgk.droid). 4 | 5 | The application's sole purpose is to provide a nice user experience while browsing the [open database of content](https://db.chgk.info/). The app does not access any personal and sensitive user data. 6 | 7 | The application uses [Google Analytics for Firebase](https://firebase.google.com/products/analytics) to help the developer improve the functionality based on anonymized usage data. 8 | 9 | In case of any questions, contact the developer via email [que.ou.quand@gmail.com](mailto:que.ou.quand@gmail.com). 10 | -------------------------------------------------------------------------------- /screenshots/dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark.png -------------------------------------------------------------------------------- /screenshots/dark/01-splash_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/01-splash_screen.jpg -------------------------------------------------------------------------------- /screenshots/dark/02-latest.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/02-latest.jpg -------------------------------------------------------------------------------- /screenshots/dark/03-latest_scrolled.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/03-latest_scrolled.jpg -------------------------------------------------------------------------------- /screenshots/dark/04-tournament.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/04-tournament.jpg -------------------------------------------------------------------------------- /screenshots/dark/05-tournament_menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/05-tournament_menu.jpg -------------------------------------------------------------------------------- /screenshots/dark/06-tournament_about.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/06-tournament_about.jpg -------------------------------------------------------------------------------- /screenshots/dark/07-tournaments_tree.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/07-tournaments_tree.jpg -------------------------------------------------------------------------------- /screenshots/dark/08-search.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/08-search.jpg -------------------------------------------------------------------------------- /screenshots/dark/09-settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/09-settings.jpg -------------------------------------------------------------------------------- /screenshots/dark/10-question1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/10-question1.jpg -------------------------------------------------------------------------------- /screenshots/dark/11-question2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/11-question2.jpg -------------------------------------------------------------------------------- /screenshots/dark/12-search2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/12-search2.jpg -------------------------------------------------------------------------------- /screenshots/dark/13-tournament2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/13-tournament2.jpg -------------------------------------------------------------------------------- /screenshots/dark/14-question3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/14-question3.jpg -------------------------------------------------------------------------------- /screenshots/dark/15-about.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/15-about.jpg -------------------------------------------------------------------------------- /screenshots/dark/16-tournaments_tree2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/16-tournaments_tree2.jpg -------------------------------------------------------------------------------- /screenshots/dark/17-tournaments_tree3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark/17-tournaments_tree3.jpg -------------------------------------------------------------------------------- /screenshots/dark_minimized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/dark_minimized.png -------------------------------------------------------------------------------- /screenshots/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light.png -------------------------------------------------------------------------------- /screenshots/light/01-splash_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/01-splash_screen.jpg -------------------------------------------------------------------------------- /screenshots/light/02-latest.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/02-latest.jpg -------------------------------------------------------------------------------- /screenshots/light/03-latest_scrolled.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/03-latest_scrolled.jpg -------------------------------------------------------------------------------- /screenshots/light/04-tournament.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/04-tournament.jpg -------------------------------------------------------------------------------- /screenshots/light/05-tournament_menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/05-tournament_menu.jpg -------------------------------------------------------------------------------- /screenshots/light/06-tournament_about.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/06-tournament_about.jpg -------------------------------------------------------------------------------- /screenshots/light/07-tournaments_tree.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/07-tournaments_tree.jpg -------------------------------------------------------------------------------- /screenshots/light/08-search.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/08-search.jpg -------------------------------------------------------------------------------- /screenshots/light/09-settings.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/09-settings.jpg -------------------------------------------------------------------------------- /screenshots/light/10-question1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/10-question1.jpg -------------------------------------------------------------------------------- /screenshots/light/11-question2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/11-question2.jpg -------------------------------------------------------------------------------- /screenshots/light/12-search2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/12-search2.jpg -------------------------------------------------------------------------------- /screenshots/light/13-tournament2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/13-tournament2.jpg -------------------------------------------------------------------------------- /screenshots/light/14-question3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/14-question3.jpg -------------------------------------------------------------------------------- /screenshots/light/15-about.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/15-about.jpg -------------------------------------------------------------------------------- /screenshots/light/16-tournaments_tree2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/16-tournaments_tree2.jpg -------------------------------------------------------------------------------- /screenshots/light/17-tournaments_tree3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light/17-tournaments_tree3.jpg -------------------------------------------------------------------------------- /screenshots/light_minimized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/screenshots/light_minimized.png -------------------------------------------------------------------------------- /www-app/app/www_app/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /www-app/app/www_app/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/app/www_app/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "", 4 | "firebase_url": "", 5 | "project_id": "", 6 | "storage_bucket": "" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "", 12 | "android_client_info": { 13 | "package_name": "chgk.droid" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "" 25 | } 26 | ], 27 | "services": { 28 | "analytics_service": { 29 | "status": 1 30 | }, 31 | "appinvite_service": { 32 | "status": 1, 33 | "other_platform_oauth_client": [] 34 | }, 35 | "ads_service": { 36 | "status": 2 37 | } 38 | } 39 | } 40 | ], 41 | "configuration_version": "1" 42 | } -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/kotlin/droid/chgk/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package chgk.droid 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/drawable/launcher_icon_background.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/drawable/screen_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/mipmap-anydpi-v26/launcher_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #212121 4 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/values-ru/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Сова 4 | 5 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/values-uk/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Сова 4 | 5 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #004D40 4 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Sova 4 | 5 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.7.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.1.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | classpath 'com.google.gms:google-services:4.3.14' 12 | classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2' 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | google() 19 | mavenCentral() 20 | } 21 | } 22 | 23 | rootProject.buildDir = '../build' 24 | subprojects { 25 | project.buildDir = "${rootProject.buildDir}/${project.name}" 26 | } 27 | subprojects { 28 | project.evaluationDependsOn(':app') 29 | } 30 | 31 | tasks.register("clean", Delete) { 32 | delete rootProject.buildDir 33 | } 34 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip 6 | -------------------------------------------------------------------------------- /www-app/app/www_app/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /www-app/app/www_app/assets/timer.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/assets/timer.mp3 -------------------------------------------------------------------------------- /www-app/app/www_app/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 11.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/app/www_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | "CFBundleDisplayName" = "Sova"; 2 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/ru.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | "CFBundleDisplayName" = "Сова"; 2 | -------------------------------------------------------------------------------- /www-app/app/www_app/ios/Runner/uk.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | "CFBundleDisplayName" = "Сова"; 2 | -------------------------------------------------------------------------------- /www-app/app/www_app/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_app/src/app.dart'; 3 | import 'package:www_app_di/www_app_di.dart'; 4 | import 'package:www_redux_store/www_redux_store.dart'; 5 | 6 | void main() { 7 | final diContainer = createDIContainer(); 8 | 9 | runApp(WWWApp( 10 | store: diContainer(), 11 | container: diContainer, 12 | )); 13 | } 14 | -------------------------------------------------------------------------------- /www-app/app/www_app/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_app 2 | description: What? When? Where? 3 | version: 2.3.1+20301 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ^3.4.1 8 | flutter: ^3.22.1 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | www_app_di: 14 | path: ../www_app_di 15 | www_widgets: 16 | path: ../../design/www_widgets 17 | 18 | dev_dependencies: 19 | www_analysis: 20 | path: ../../utils/www_analysis 21 | 22 | flutter: 23 | uses-material-design: true 24 | assets: 25 | - assets/ 26 | 27 | dependency_overrides: 28 | package_info_plus: 4.1.0 # caused by app_review: 2.1.2+1 29 | -------------------------------------------------------------------------------- /www-app/app/www_app_di/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/app/www_app_di/lib/src/di/di_container.dart: -------------------------------------------------------------------------------- 1 | abstract class IContainer { 2 | T call(); 3 | } 4 | -------------------------------------------------------------------------------- /www-app/app/www_app_di/lib/src/di/di_container_implementation.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:www_app_di/src/di/di_container.dart'; 3 | import 'package:www_app_di/src/di/di_module.dart'; 4 | 5 | final _getIt = GetIt.instance; 6 | 7 | class _WWWDIContainer implements IContainer { 8 | const _WWWDIContainer(this._getIt); 9 | 10 | final GetIt _getIt; 11 | 12 | @override 13 | T call() => _getIt(); 14 | } 15 | 16 | IContainer createDIContainer() { 17 | const WWWDIModuleApp().init(_getIt); 18 | return _WWWDIContainer(_getIt); 19 | } 20 | -------------------------------------------------------------------------------- /www-app/app/www_app_di/lib/www_app_di.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_app_di/src/di/di_container.dart'; 2 | export 'package:www_app_di/src/di/di_container_implementation.dart'; 3 | -------------------------------------------------------------------------------- /www-app/app/www_navigation/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/app/www_navigation/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get_it/get_it.dart'; 3 | import 'package:injectable/injectable.dart'; 4 | import 'package:www_di/www_di.dart'; 5 | import 'package:www_navigation/src/di/di_module.config.dart'; 6 | 7 | class WWWDIModuleNavigation extends WWWDIModule { 8 | const WWWDIModuleNavigation() : super(_init); 9 | } 10 | 11 | @injectableInit 12 | void _init(GetIt getIt) => getIt.init(); 13 | 14 | @module 15 | abstract class RegisterModule { 16 | @lazySingleton 17 | GlobalKey get key => GlobalKey(); 18 | } 19 | -------------------------------------------------------------------------------- /www-app/app/www_navigation/lib/www_navigation.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_navigation/src/di/di_module.dart'; 2 | export 'package:www_navigation/src/redux/middleware.dart'; 3 | -------------------------------------------------------------------------------- /www-app/app/www_redux_store/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/app/www_redux_store/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_redux_store/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleReduxStore extends WWWDIModule { 7 | const WWWDIModuleReduxStore() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/app/www_redux_store/lib/src/loggers/logs/middleware.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:redux/redux.dart'; 3 | import 'package:www_logger/www_logger.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | 6 | @injectable 7 | class LogsMiddleware implements IMiddleware { 8 | @override 9 | Iterable> get middleware => _middleware; 10 | late final _middleware = _createMiddleware(); 11 | 12 | List> _createMiddleware() => [ 13 | TypedMiddleware(_onLog), 14 | ]; 15 | 16 | void _onLog(Store store, dynamic action, NextDispatcher next) { 17 | log(action.runtimeType); 18 | 19 | next(action); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /www-app/app/www_redux_store/lib/src/redux/store.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:redux/redux.dart'; 3 | import 'package:www_redux_store/src/redux/middleware.dart'; 4 | import 'package:www_redux_store/src/redux/reducer.dart'; 5 | import 'package:www_redux_store/src/redux/state.dart'; 6 | 7 | @injectable 8 | class WWWStore extends Store { 9 | WWWStore({ 10 | required AppMiddleware appMiddleware, 11 | required AppReducer appReducer, 12 | }) : super( 13 | appReducer.reducer, 14 | initialState: AppState.initial(), 15 | middleware: appMiddleware.middleware.toList(), 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /www-app/app/www_redux_store/lib/www_redux_store.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_redux_store/src/di/di_module.dart'; 2 | export 'package:www_redux_store/src/redux/state.dart'; 3 | export 'package:www_redux_store/src/redux/store.dart'; 4 | -------------------------------------------------------------------------------- /www-app/app/www_redux_store/test/mocks/fakes.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_redux/www_redux.dart'; 2 | 3 | class TestState implements IState { 4 | const TestState(); 5 | } 6 | -------------------------------------------------------------------------------- /www-app/app/www_redux_store/test/mocks/mocks.dart: -------------------------------------------------------------------------------- 1 | import 'package:mocktail/mocktail.dart'; 2 | import 'package:www_analytics/www_analytics.dart'; 3 | 4 | class MockAnalyticsService extends Mock implements IAnalyticsService {} 5 | -------------------------------------------------------------------------------- /www-app/core/www_constants/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/core/www_constants/lib/src/constants.dart: -------------------------------------------------------------------------------- 1 | abstract class WWWConstants { 2 | static const databaseUrl = 'https://db.chgk.info'; 3 | static const playMarketLink = 4 | 'https://play.google.com/store/apps/details?id=chgk.droid'; 5 | static const appStoreLink = ''; 6 | static const developerEmail = 'que.ou.quand@gmail.com'; 7 | static const developerWebsite = 'https://foxanna.github.io/'; 8 | static const privacyPolicyLink = 'https://github.com/foxanna/WWW-flutter/blob/main/PRIVACY_POLICY.md'; 9 | } 10 | -------------------------------------------------------------------------------- /www-app/core/www_constants/lib/www_constants.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_constants/src/constants.dart'; 2 | -------------------------------------------------------------------------------- /www-app/core/www_constants/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_constants 2 | description: Application constants 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | dev_dependencies: 14 | www_analysis: 15 | path: ../../utils/www_analysis 16 | -------------------------------------------------------------------------------- /www-app/core/www_http/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/core/www_http/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_http/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleHttp extends WWWDIModule { 7 | const WWWDIModuleHttp() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/core/www_http/lib/src/dio/dio_config/dio_config_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:get_it/get_it.dart'; 3 | import 'package:injectable/injectable.dart'; 4 | import 'package:www_constants/www_constants.dart'; 5 | import 'package:www_http/src/dio/dio_config/dio_config_parameters.dart'; 6 | import 'package:www_http/src/dio/dio_factory.dart'; 7 | 8 | @module 9 | abstract class DioConfigInjectableModule { 10 | @Named(DioConfigParameters.baseUrl) 11 | String get baseUrl => WWWConstants.databaseUrl; 12 | 13 | @Named(DioConfigParameters.connectTimeout) 14 | Duration get connectTimeout => const Duration(seconds: 30); 15 | 16 | @Named(DioConfigParameters.receiveTimeout) 17 | Duration get receiveTimeout => const Duration(seconds: 60); 18 | 19 | @Named(DioConfigParameters.logHttpCommunication) 20 | bool get logHttpCommunication => true; 21 | 22 | @Named(DioConfigParameters.logHttpResponseContent) 23 | bool get logHttpResponseContent => false; 24 | 25 | @lazySingleton 26 | Dio get dio => GetIt.instance().create(); 27 | } 28 | -------------------------------------------------------------------------------- /www-app/core/www_http/lib/src/dio/dio_config/dio_config_parameters.dart: -------------------------------------------------------------------------------- 1 | abstract class DioConfigParameters { 2 | static const baseUrl = 'baseUrl'; 3 | static const connectTimeout = 'connectTimeout'; 4 | static const receiveTimeout = 'receiveTimeout'; 5 | static const logHttpCommunication = 'logHttpCommunication'; 6 | static const logHttpResponseContent = 'logHttpResponseContent'; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/core/www_http/lib/src/service/http_client.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_utils/www_utils.dart'; 4 | 5 | abstract class IHttpClient { 6 | Future get(Uri uri, {CancelToken cancelToken}); 7 | } 8 | 9 | @LazySingleton(as: IHttpClient) 10 | class HttpClient implements IHttpClient { 11 | const HttpClient({ 12 | required Dio dio, 13 | }) : _dio = dio; 14 | 15 | final Dio _dio; 16 | 17 | @override 18 | Future get(Uri uri, {CancelToken? cancelToken}) async { 19 | try { 20 | final response = 21 | await _dio.get(uri.toString(), cancelToken: cancelToken); 22 | return response.data ?? ''; 23 | } on DioException catch (e) { 24 | throw NetworkException(message: e.toString()); 25 | } on Exception { 26 | rethrow; 27 | } on Error catch (e) { 28 | throw Exception(e.toString()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /www-app/core/www_http/lib/www_http.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_http/src/di/di_module.dart'; 2 | export 'package:www_http/src/service/http_client.dart'; 3 | -------------------------------------------------------------------------------- /www-app/core/www_http/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_http 2 | description: Http client 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | dio: ^5.3.2 11 | flutter: 12 | sdk: flutter 13 | injectable: 2.4.2 14 | www_constants: 15 | path: ../www_constants/ 16 | www_di: 17 | path: ../../utils/www_di/ 18 | www_logger: 19 | path: ../../utils/www_logger/ 20 | www_utils: 21 | path: ../../utils/www_utils 22 | 23 | dev_dependencies: 24 | build_runner: 2.4.11 25 | injectable_generator: 2.6.1 26 | www_analysis: 27 | path: ../../utils/www_analysis 28 | -------------------------------------------------------------------------------- /www-app/core/www_localization/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/core/www_localization/lib/src/extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:www_localization/src/localizations.dart'; 3 | import 'package:www_localization/src/translations/translations.i69n.dart'; 4 | 5 | extension BuildContextLocalizationX on BuildContext { 6 | Translations get translations => WWWLocalizations.of(this); 7 | } 8 | -------------------------------------------------------------------------------- /www-app/core/www_localization/lib/www_localization.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_localization/src/extensions.dart'; 2 | export 'package:www_localization/src/localizations.dart'; 3 | export 'package:www_localization/src/translations/translations.i69n.dart'; 4 | -------------------------------------------------------------------------------- /www-app/core/www_localization/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_localization 2 | description: Localization resources for www_* packages 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | flutter_localizations: 13 | sdk: flutter 14 | i69n: ^2.1.0 15 | 16 | dev_dependencies: 17 | build_runner: 2.4.11 18 | www_analysis: 19 | path: ../../utils/www_analysis 20 | -------------------------------------------------------------------------------- /www-app/design/www_custom_icons/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/design/www_custom_icons/assets/CustomIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxanna/WWW-flutter/c441026d634d10c652a90f68983c694ae9106a09/www-app/design/www_custom_icons/assets/CustomIcons.ttf -------------------------------------------------------------------------------- /www-app/design/www_custom_icons/lib/src/custom_icons.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class WWWCustomIcons { 4 | WWWCustomIcons._(); 5 | 6 | static const _kFontFam = 'CustomIcons'; 7 | static const String? _kFontPkg = 'www_custom_icons'; 8 | 9 | static const IconData random_card = 10 | IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); 11 | static const IconData bookmarks = 12 | IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); 13 | static const IconData tree = 14 | IconData(0xe805, fontFamily: _kFontFam, fontPackage: _kFontPkg); 15 | static const IconData settings = 16 | IconData(0xe806, fontFamily: _kFontFam, fontPackage: _kFontPkg); 17 | } 18 | -------------------------------------------------------------------------------- /www-app/design/www_custom_icons/lib/www_custom_icons.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_custom_icons/src/custom_icons.dart'; 2 | -------------------------------------------------------------------------------- /www-app/design/www_custom_icons/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_custom_icons 2 | description: A wrapper over icons font for www_* features 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | dev_dependencies: 14 | www_analysis: 15 | path: ../../utils/www_analysis 16 | 17 | flutter: 18 | fonts: 19 | - family: CustomIcons 20 | fonts: 21 | - asset: assets/CustomIcons.ttf 22 | -------------------------------------------------------------------------------- /www-app/design/www_theme/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/design/www_theme/lib/src/dimensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Dimensions { 4 | Dimensions._(); 5 | 6 | static const defaultPadding = EdgeInsets.all(defaultSidePadding); 7 | static const defaultSidePadding = 8.0; 8 | static const defaultSpacing = 8.0; 9 | static const dialogContentPadding = 10 | EdgeInsets.symmetric(vertical: 24, horizontal: 24); 11 | 12 | static const double mediumComponentsCornerRadiusValue = 16.0; 13 | static const double largeComponentsCornerRadiusValue = 32.0; 14 | } 15 | -------------------------------------------------------------------------------- /www-app/design/www_theme/lib/src/extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:www_theme/src/style_configuration.dart'; 3 | 4 | extension BuildContextStyleConfigurationX on BuildContext { 5 | StyleConfiguration get styleConfig => StyleConfiguration.of(this); 6 | } 7 | -------------------------------------------------------------------------------- /www-app/design/www_theme/lib/src/style_configurator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_theme/src/style_configuration.dart'; 3 | 4 | class StyleConfigurator extends StatelessWidget { 5 | const StyleConfigurator({Key? key, required this.child}) : super(key: key); 6 | 7 | final Widget child; 8 | 9 | @override 10 | Widget build(BuildContext context) => StyleConfigurationInheritedWidget( 11 | styleConfiguration: StyleConfiguration(context: context), 12 | child: child, 13 | ); 14 | } 15 | 16 | class StyleConfigurationInheritedWidget extends InheritedWidget { 17 | const StyleConfigurationInheritedWidget({ 18 | Key? key, 19 | required Widget child, 20 | required this.styleConfiguration, 21 | }) : super( 22 | key: key, 23 | child: child, 24 | ); 25 | 26 | final StyleConfiguration styleConfiguration; 27 | 28 | @override 29 | bool updateShouldNotify(StyleConfigurationInheritedWidget oldWidget) => 30 | this.styleConfiguration != oldWidget.styleConfiguration; 31 | } 32 | -------------------------------------------------------------------------------- /www-app/design/www_theme/lib/www_theme.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_theme/src/dimensions.dart'; 2 | export 'package:www_theme/src/extensions.dart'; 3 | export 'package:www_theme/src/style_configuration.dart'; 4 | export 'package:www_theme/src/style_configurator.dart'; 5 | export 'package:www_theme/src/text_sections_theme_data.dart'; 6 | export 'package:www_theme/src/themes.dart'; 7 | -------------------------------------------------------------------------------- /www-app/design/www_theme/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_theme 2 | description: Theme and styles for www_* features 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | dev_dependencies: 14 | www_analysis: 15 | path: ../../utils/www_analysis 16 | -------------------------------------------------------------------------------- /www-app/design/www_widgets/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/design/www_widgets/lib/src/animated_fab.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class AnimatedFab extends StatelessWidget { 4 | const AnimatedFab({ 5 | Key? key, 6 | required this.visible, 7 | this.onPressed, 8 | required this.child, 9 | }) : super(key: key); 10 | 11 | final bool visible; 12 | final VoidCallback? onPressed; 13 | final Widget child; 14 | 15 | @override 16 | Widget build(BuildContext context) => AnimatedScale( 17 | scale: visible ? 1.0 : 0.8, 18 | duration: const Duration(milliseconds: 150), 19 | child: AnimatedOpacity( 20 | opacity: visible ? 1.0 : 0.0, 21 | duration: const Duration(milliseconds: 150), 22 | child: Visibility( 23 | visible: visible, 24 | child: FloatingActionButton( 25 | onPressed: onPressed, 26 | child: child, 27 | ), 28 | ), 29 | ), 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /www-app/design/www_widgets/lib/src/empty_sliver.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class EmptySliver extends StatelessWidget { 4 | const EmptySliver({Key? key}) : super(key: key); 5 | 6 | @override 7 | Widget build(BuildContext context) => SliverFillRemaining( 8 | hasScrollBody: false, 9 | child: Container(), 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /www-app/design/www_widgets/lib/src/gradient_decoration.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | @immutable 4 | class GradientDecoration extends BoxDecoration { 5 | factory GradientDecoration({required Color color}) { 6 | final gradientEnd = color; 7 | final gradientStart = color.withAlpha(0); 8 | const gradientSize = 0.05; 9 | final gradient = LinearGradient( 10 | begin: Alignment.topCenter, 11 | end: Alignment.bottomCenter, 12 | colors: [gradientEnd, gradientStart, gradientStart, gradientEnd], 13 | stops: const [0, gradientSize, 1 - gradientSize, 1]); 14 | return GradientDecoration._(gradient: gradient); 15 | } 16 | 17 | const GradientDecoration._({required Gradient gradient}) 18 | : super(gradient: gradient); 19 | } 20 | -------------------------------------------------------------------------------- /www-app/design/www_widgets/lib/src/modal_bottom_sheet_container.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_theme/www_theme.dart'; 3 | 4 | class ModalBottomSheetContainer extends StatelessWidget { 5 | const ModalBottomSheetContainer({ 6 | Key? key, 7 | required this.children, 8 | }) : super(key: key); 9 | 10 | final List children; 11 | 12 | @override 13 | Widget build(BuildContext context) => Padding( 14 | padding: 15 | context.styleConfig.bottomSheetStyleConfiguration.contentPadding, 16 | child: Column( 17 | mainAxisSize: MainAxisSize.min, 18 | children: children, 19 | ), 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /www-app/design/www_widgets/lib/src/progress_indicator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class WWWProgressIndicator extends StatelessWidget { 4 | const WWWProgressIndicator({Key? key}) : super(key: key); 5 | 6 | @override 7 | Widget build(BuildContext context) => 8 | const Center(child: CircularProgressIndicator()); 9 | } 10 | -------------------------------------------------------------------------------- /www-app/design/www_widgets/lib/src/status_bar_brightness.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | class WWWStatusBarBrightness extends StatelessWidget { 5 | const WWWStatusBarBrightness({ 6 | Key? key, 7 | required this.statusBarBrightness, 8 | required this.child, 9 | }) : super(key: key); 10 | 11 | final Widget child; 12 | final Brightness statusBarBrightness; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | final theme = Theme.of(context); 17 | 18 | return AnnotatedRegion( 19 | value: statusBarBrightness == Brightness.light 20 | ? SystemUiOverlayStyle.light 21 | : SystemUiOverlayStyle.dark, 22 | child: Theme( 23 | data: theme.copyWith( 24 | appBarTheme: theme.appBarTheme, 25 | ), 26 | child: child, 27 | ), 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /www-app/design/www_widgets/lib/src/unexpected_state_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_localization/www_localization.dart'; 3 | 4 | class UnexpectedStateWidget extends StatelessWidget { 5 | const UnexpectedStateWidget({Key? key}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) => Padding( 9 | padding: const EdgeInsets.all(8), 10 | child: Center( 11 | child: Text(context.translations.errorMessageGeneric, 12 | textAlign: TextAlign.center, 13 | style: Theme.of(context).textTheme.bodySmall), 14 | ), 15 | ); 16 | } 17 | 18 | class UnexpectedStateSliver extends StatelessWidget { 19 | const UnexpectedStateSliver({Key? key}) : super(key: key); 20 | 21 | @override 22 | Widget build(BuildContext context) => 23 | const SliverToBoxAdapter(child: UnexpectedStateWidget()); 24 | } 25 | -------------------------------------------------------------------------------- /www-app/design/www_widgets/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_widgets 2 | description: Common widgets for www_* features 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | auto_size_text: ^3.0.0 11 | flutter: 12 | sdk: flutter 13 | flutter_staggered_grid_view: ^0.7.0 14 | shimmer: ^3.0.0 15 | www_localization: 16 | path: ../../core/www_localization 17 | www_models: 18 | path: ../../domain/www_models 19 | www_theme: 20 | path: ../www_theme 21 | www_utils: 22 | path: ../../utils/www_utils 23 | 24 | dev_dependencies: 25 | www_analysis: 26 | path: ../../utils/www_analysis 27 | -------------------------------------------------------------------------------- /www-app/domain/www_api/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/domain/www_api/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | json_serializable: 5 | options: 6 | include_if_null: false 7 | explicit_to_json: true 8 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_api/src/di/di_module.config.dart'; 4 | import 'package:www_di/www_di.dart'; 5 | 6 | class WWWDIModuleApi extends WWWDIModule { 7 | const WWWDIModuleApi() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/json_converters/questions_list_converter.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_api/src/models/question_dto.dart'; 3 | 4 | class QuestionsListConverter 5 | implements JsonConverter?, Object?> { 6 | const QuestionsListConverter(); 7 | 8 | @override 9 | List? fromJson(Object? json) { 10 | if (json is List) { 11 | return List>.from(json) 12 | .map((q) => QuestionDto.fromJson(q)) 13 | .toList(); 14 | } 15 | 16 | if (json is Map) { 17 | return [QuestionDto.fromJson(json)]; 18 | } 19 | 20 | return null; 21 | } 22 | 23 | @override 24 | Object? toJson(List? object) => object; 25 | } 26 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/json_converters/tours_list_converter.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_api/src/models/tour_dto.dart'; 3 | 4 | class ToursListConverter implements JsonConverter?, Object?> { 5 | const ToursListConverter(); 6 | 7 | @override 8 | List? fromJson(Object? json) { 9 | if (json is List) { 10 | return List>.from(json) 11 | .map((q) => TourDto.fromJson(q)) 12 | .toList(); 13 | } 14 | 15 | if (json is Map) { 16 | return [TourDto.fromJson(json)]; 17 | } 18 | 19 | return null; 20 | } 21 | 22 | @override 23 | Object? toJson(List? object) => object; 24 | } 25 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/latest_tournaments_dto.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_api/src/models/tournament_dto.dart'; 3 | 4 | part 'latest_tournaments_dto.freezed.dart'; 5 | part 'latest_tournaments_dto.g.dart'; 6 | 7 | @freezed 8 | class LatestTournamentsDto with _$LatestTournamentsDto { 9 | const factory LatestTournamentsDto({ 10 | @JsonKey(name: 'latest') List? tournaments, 11 | }) = _LatestTournamentsDto; 12 | 13 | factory LatestTournamentsDto.fromJson(Map json) => 14 | _$LatestTournamentsDtoFromJson(json); 15 | } 16 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/latest_tournaments_dto.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'latest_tournaments_dto.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$LatestTournamentsDtoImpl _$$LatestTournamentsDtoImplFromJson( 10 | Map json) => 11 | _$LatestTournamentsDtoImpl( 12 | tournaments: (json['latest'] as List?) 13 | ?.map((e) => TournamentDto.fromJson(e as Map)) 14 | .toList(), 15 | ); 16 | 17 | Map _$$LatestTournamentsDtoImplToJson( 18 | _$LatestTournamentsDtoImpl instance) { 19 | final val = {}; 20 | 21 | void writeNotNull(String key, dynamic value) { 22 | if (value != null) { 23 | val[key] = value; 24 | } 25 | } 26 | 27 | writeNotNull('latest', instance.tournaments?.map((e) => e.toJson()).toList()); 28 | return val; 29 | } 30 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/model_converters/question_parser/question_section_type.dart: -------------------------------------------------------------------------------- 1 | enum QuestionSectionType { 2 | Text, 3 | SpeakerNote, 4 | GiveAway, 5 | Image, 6 | Audio, 7 | } 8 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/model_converters/random_questions_converter.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_api/src/models/model_converters/question_converter.dart'; 2 | import 'package:www_api/src/models/random_questions_dto.dart'; 3 | import 'package:www_models/www_models.dart'; 4 | 5 | extension RandomQuestionsDtoX on RandomQuestionsDto { 6 | RandomQuestions toModel() => RandomQuestions( 7 | questions: 8 | this.search?.map((questionDto) => questionDto.toModel()).toList() ?? 9 | [], 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/random_questions_dto.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_api/src/models/json_converters/questions_list_converter.dart'; 3 | import 'package:www_api/src/models/question_dto.dart'; 4 | 5 | part 'random_questions_dto.freezed.dart'; 6 | part 'random_questions_dto.g.dart'; 7 | 8 | @freezed 9 | class RandomQuestionsDto with _$RandomQuestionsDto { 10 | const factory RandomQuestionsDto({ 11 | @JsonKey(name: 'question') 12 | @QuestionsListConverter() 13 | List? search, 14 | }) = _RandomQuestionsDto; 15 | 16 | factory RandomQuestionsDto.fromJson(Map json) => 17 | _$RandomQuestionsDtoFromJson(json); 18 | } 19 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/random_questions_dto.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'random_questions_dto.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$RandomQuestionsDtoImpl _$$RandomQuestionsDtoImplFromJson( 10 | Map json) => 11 | _$RandomQuestionsDtoImpl( 12 | search: const QuestionsListConverter().fromJson(json['question']), 13 | ); 14 | 15 | Map _$$RandomQuestionsDtoImplToJson( 16 | _$RandomQuestionsDtoImpl instance) { 17 | final val = {}; 18 | 19 | void writeNotNull(String key, dynamic value) { 20 | if (value != null) { 21 | val[key] = value; 22 | } 23 | } 24 | 25 | writeNotNull( 26 | 'question', const QuestionsListConverter().toJson(instance.search)); 27 | return val; 28 | } 29 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/search_tournaments_dto.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_api/src/models/tournament_dto.dart'; 3 | 4 | part 'search_tournaments_dto.freezed.dart'; 5 | part 'search_tournaments_dto.g.dart'; 6 | 7 | @freezed 8 | class SearchTournamentsDto with _$SearchTournamentsDto { 9 | const factory SearchTournamentsDto({ 10 | @JsonKey(name: 'search') List? tournaments, 11 | }) = _SearchTournamentsDto; 12 | 13 | factory SearchTournamentsDto.fromJson(Map json) => 14 | _$SearchTournamentsDtoFromJson(json); 15 | } 16 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/search_tournaments_dto.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'search_tournaments_dto.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$SearchTournamentsDtoImpl _$$SearchTournamentsDtoImplFromJson( 10 | Map json) => 11 | _$SearchTournamentsDtoImpl( 12 | tournaments: (json['search'] as List?) 13 | ?.map((e) => TournamentDto.fromJson(e as Map)) 14 | .toList(), 15 | ); 16 | 17 | Map _$$SearchTournamentsDtoImplToJson( 18 | _$SearchTournamentsDtoImpl instance) { 19 | final val = {}; 20 | 21 | void writeNotNull(String key, dynamic value) { 22 | if (value != null) { 23 | val[key] = value; 24 | } 25 | } 26 | 27 | writeNotNull('search', instance.tournaments?.map((e) => e.toJson()).toList()); 28 | return val; 29 | } 30 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/models/tournaments_tree_dto.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_api/src/models/json_converters/tournaments_tree_converter.dart'; 3 | 4 | part 'tournaments_tree_dto.freezed.dart'; 5 | part 'tournaments_tree_dto.g.dart'; 6 | 7 | @freezed 8 | class TournamentsTreeDto with _$TournamentsTreeDto { 9 | const factory TournamentsTreeDto({ 10 | @JsonKey(name: 'Id') String? id, 11 | @JsonKey(name: 'Title') String? title, 12 | @JsonKey(name: 'ChildrenNum') String? childrenCount, 13 | @JsonKey(name: 'tour') @TournamentsTreeConverter() List? children, 14 | }) = _TournamentsTreeDto; 15 | 16 | factory TournamentsTreeDto.fromJson(Map json) => 17 | _$TournamentsTreeDtoFromJson(json); 18 | } 19 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/src/parsers/xml2json_parser.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:injectable/injectable.dart'; 4 | import 'package:www_utils/www_utils.dart'; 5 | import 'package:xml2json/xml2json.dart'; 6 | 7 | abstract class IXmlToJsonParser { 8 | Map toJson(String data); 9 | } 10 | 11 | @LazySingleton(as: IXmlToJsonParser) 12 | class XmlToJsonParser implements IXmlToJsonParser { 13 | @override 14 | Map toJson(String xml) { 15 | final transformer = Xml2Json(); 16 | transformer.parse(xml.escapeBackSlashes()); 17 | final json = transformer.toParker(); 18 | final decoded = jsonDecode(json) as Map; 19 | return decoded; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /www-app/domain/www_api/lib/www_api.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_api/src/di/di_module.dart'; 2 | export 'package:www_api/src/loaders/latest_tournaments_loader.dart'; 3 | export 'package:www_api/src/loaders/random_questions_loader.dart'; 4 | export 'package:www_api/src/loaders/search_loader.dart'; 5 | export 'package:www_api/src/loaders/tour_details_loader.dart'; 6 | export 'package:www_api/src/loaders/tournament_details_loader.dart'; 7 | export 'package:www_api/src/loaders/tournaments_tree_loader.dart'; 8 | -------------------------------------------------------------------------------- /www-app/domain/www_api/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_api 2 | description: https://db.chgk.info/ API 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | freezed_annotation: 2.4.1 13 | html: ^0.15.4 14 | injectable: 2.4.2 15 | json_annotation: 4.9.0 16 | www_background_runner: 17 | path: ../../utils/www_background_runner 18 | www_constants: 19 | path: ../../core/www_constants/ 20 | www_di: 21 | path: ../../utils/www_di/ 22 | www_http: 23 | path: ../../core/www_http 24 | www_models: 25 | path: ../www_models 26 | www_utils: 27 | path: ../../utils/www_utils 28 | xml2json: ^6.2.3 29 | 30 | dev_dependencies: 31 | build_runner: 2.4.11 32 | flutter_test: 33 | sdk: flutter 34 | freezed: 2.5.2 35 | injectable_generator: 2.6.1 36 | json_serializable: 6.8.0 37 | www_analysis: 38 | path: ../../utils/www_analysis 39 | www_test_utils: 40 | path: ../../utils/www_test_utils 41 | -------------------------------------------------------------------------------- /www-app/domain/www_api/test/loaders/random_questions/test_data_3.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_models/www_models.dart'; 2 | 3 | const expectedRandomQuestions3 = []; 4 | 5 | const randomQuestionsApiResponse3 = ''' 6 | 7 | 8 | 9 | 10 | 11 | '''; 12 | -------------------------------------------------------------------------------- /www-app/domain/www_api/test/loaders/tournament_details/test_data_3.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_models/www_models.dart'; 2 | 3 | const expectedTournamentDetails3 = Tournament( 4 | id: '14352', 5 | id2: 'zzz', 6 | info: TournamentInfo( 7 | id: '14352', 8 | id2: 'zzz', 9 | title: r'''ZZZZZZZ''', 10 | questionsCount: '0', 11 | url: r'''https://db.chgk.info/tour/14352''', 12 | ), 13 | tours: [], 14 | ); 15 | 16 | const tournamentDetailsApiResponse3 = ''' 17 | 18 | 19 | 14352 20 | 0 21 | ZZZZZZZ 22 | 23 | zzz 24 | 0 25 | 26 | Ч 27 | 28 | 29 | 30 | 31 | 32 | 33 | thanos19.5_u.txt 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 7773 42 | 0 43 | 44 | '''; 45 | -------------------------------------------------------------------------------- /www-app/domain/www_api/test/mocks/fakes.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter_test/flutter_test.dart'; 4 | import 'package:www_background_runner/www_background_runner.dart'; 5 | 6 | class FakeBackgroundRunnerService extends Fake 7 | implements IBackgroundRunnerService { 8 | @override 9 | Future init() => Future.value(); 10 | 11 | @override 12 | Future run( 13 | FutureOr Function(P argument) function, P argument) async { 14 | final result = await function(argument); 15 | return result; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /www-app/domain/www_api/test/mocks/mocks.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:mocktail/mocktail.dart'; 3 | import 'package:www_background_runner/www_background_runner.dart'; 4 | import 'package:www_http/www_http.dart'; 5 | 6 | class MockDio extends Mock implements Dio {} 7 | 8 | class MockHttpClient extends Mock implements IHttpClient {} 9 | 10 | class MockBackgroundRunnerService extends Mock 11 | implements IBackgroundRunnerService {} 12 | -------------------------------------------------------------------------------- /www-app/domain/www_cache/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/domain/www_cache/lib/src/cache/tournaments_cache.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:www_models/www_models.dart'; 3 | 4 | abstract class ITournamentsCache { 5 | bool contains(String id); 6 | 7 | void save(Tournament tournament); 8 | 9 | Tournament? get(String id); 10 | } 11 | 12 | @LazySingleton(as: ITournamentsCache) 13 | class TournamentsCache implements ITournamentsCache { 14 | final _cacheById = {}; 15 | final _cacheByTextId = {}; 16 | 17 | @override 18 | bool contains(String id) => 19 | _cacheById.containsKey(id) || _cacheByTextId.containsKey(id); 20 | 21 | @override 22 | void save(Tournament tournament) { 23 | if (tournament.id != null) { 24 | _cacheById[tournament.id!] = tournament; 25 | } 26 | 27 | if (tournament.id2 != null) { 28 | _cacheByTextId[tournament.id2!] = tournament; 29 | } 30 | } 31 | 32 | @override 33 | Tournament? get(String id) => _cacheById[id] ?? _cacheByTextId[id]; 34 | } 35 | -------------------------------------------------------------------------------- /www-app/domain/www_cache/lib/src/cache/tournaments_tree_cache.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:www_models/www_models.dart'; 3 | 4 | abstract class ITournamentsTreeCache { 5 | bool contains(String id); 6 | 7 | void save(TournamentsTree tour); 8 | 9 | TournamentsTree? get(String id); 10 | } 11 | 12 | @LazySingleton(as: ITournamentsTreeCache) 13 | class TournamentsTreeCache implements ITournamentsTreeCache { 14 | final _cache = {}; 15 | 16 | @override 17 | bool contains(String id) => _cache.containsKey(id); 18 | 19 | @override 20 | void save(TournamentsTree tree) { 21 | if (tree.id != null) { 22 | _cache[tree.id!] = tree; 23 | } 24 | } 25 | 26 | @override 27 | TournamentsTree? get(String id) => _cache[id]; 28 | } 29 | -------------------------------------------------------------------------------- /www-app/domain/www_cache/lib/src/cache/tours_cache.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:www_models/www_models.dart'; 3 | 4 | abstract class IToursCache { 5 | bool contains(String id); 6 | 7 | void save(Tour tour); 8 | 9 | Tour? get(String id); 10 | } 11 | 12 | @LazySingleton(as: IToursCache) 13 | class ToursCache implements IToursCache { 14 | final _cache = {}; 15 | 16 | @override 17 | bool contains(String id) => _cache.containsKey(id); 18 | 19 | @override 20 | void save(Tour tour) { 21 | if (tour.id != null) { 22 | _cache[tour.id!] = tour; 23 | } 24 | } 25 | 26 | @override 27 | Tour? get(String id) => _cache[id]; 28 | } 29 | -------------------------------------------------------------------------------- /www-app/domain/www_cache/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_cache/src/di/di_module.config.dart'; 4 | import 'package:www_di/www_di.dart'; 5 | 6 | class WWWDIModuleCache extends WWWDIModule { 7 | const WWWDIModuleCache() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/domain/www_cache/lib/www_cache.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_cache/src/cache/cache_synchronizer.dart'; 2 | export 'package:www_cache/src/cache/tournaments_cache.dart'; 3 | export 'package:www_cache/src/cache/tournaments_tree_cache.dart'; 4 | export 'package:www_cache/src/cache/tours_cache.dart'; 5 | export 'package:www_cache/src/di/di_module.dart'; 6 | -------------------------------------------------------------------------------- /www-app/domain/www_cache/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_cache 2 | description: An in-memory cache for all www_* packages 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | injectable: 2.4.2 13 | www_analytics: 14 | path: ../../utils/www_analytics 15 | www_di: 16 | path: ../../utils/www_di/ 17 | www_local_storage: 18 | path: ../www_local_storage 19 | www_models: 20 | path: ../www_models 21 | www_utils: 22 | path: ../../utils/www_utils 23 | 24 | dev_dependencies: 25 | build_runner: 2.4.11 26 | injectable_generator: 2.6.1 27 | www_analysis: 28 | path: ../../utils/www_analysis 29 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/build.yaml: -------------------------------------------------------------------------------- 1 | global_options: 2 | freezed: 3 | runs_before: 4 | - hive_generator 5 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_local_storage/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleLocalStorage extends WWWDIModule { 7 | const WWWDIModuleLocalStorage() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/model_converters/question_info_converter.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_local_storage/src/hive/model_converters/tour_info_converter.dart'; 2 | import 'package:www_local_storage/src/hive/models/question_info.dart'; 3 | import 'package:www_models/www_models.dart'; 4 | 5 | extension QuestionInfoHiveX on QuestionInfo { 6 | QuestionInfoHiveModel toHiveModel() => QuestionInfoHiveModel( 7 | id: this.id, 8 | number: this.number, 9 | url: this.url, 10 | tourInfo: this.tourInfo.toHiveModel(), 11 | ); 12 | } 13 | 14 | extension QuestionInfoHiveModelX on QuestionInfoHiveModel { 15 | QuestionInfo toModel() => QuestionInfo( 16 | id: this.id, 17 | number: this.number, 18 | url: this.url, 19 | tourInfo: this.tourInfo?.toModel() ?? const TourInfo(), 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/model_converters/tour_converter.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_local_storage/src/hive/model_converters/question_converter.dart'; 2 | import 'package:www_local_storage/src/hive/model_converters/tour_info_converter.dart'; 3 | import 'package:www_local_storage/src/hive/models/tour.dart'; 4 | import 'package:www_models/www_models.dart'; 5 | 6 | extension TourHiveX on Tour { 7 | TourHiveModel toHiveModel() => TourHiveModel( 8 | id: this.id, 9 | info: this.info.toHiveModel(), 10 | questions: 11 | this.questions.map((question) => question.toHiveModel()).toList(), 12 | ); 13 | } 14 | 15 | extension TourHiveModelX on TourHiveModel { 16 | Tour toModel() => Tour( 17 | id: this.id, 18 | info: this.info?.toModel() ?? const TourInfo(), 19 | questions: 20 | this.questions?.map((question) => question.toModel()).toList() ?? 21 | [], 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/model_converters/tournament_status_converter.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_local_storage/src/hive/models/tournament_status.dart'; 2 | import 'package:www_models/www_models.dart'; 3 | 4 | extension TournamentStatusHiveX on TournamentStatus { 5 | TournamentStatusHiveModel toHiveModel() => TournamentStatusHiveModel( 6 | isBookmarked: this.isBookmarked, 7 | isNew: this.isNew, 8 | ); 9 | } 10 | 11 | extension TournamentStatusHiveModelX on TournamentStatusHiveModel { 12 | TournamentStatus toModel() => TournamentStatus( 13 | isBookmarked: this.isBookmarked ?? false, 14 | isNew: this.isNew ?? false, 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/models/question_info.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:hive/hive.dart'; 3 | import 'package:www_local_storage/src/hive/hive_constants.dart'; 4 | import 'package:www_local_storage/src/hive/models/tour_info.dart'; 5 | 6 | part 'question_info.freezed.dart'; 7 | part 'question_info.g.dart'; 8 | 9 | @freezed 10 | class QuestionInfoHiveModel with _$QuestionInfoHiveModel { 11 | @HiveType(typeId: HiveTypesIds.hiveQuestionInfoTypeId) 12 | const factory QuestionInfoHiveModel({ 13 | @HiveField(QuestionInfoHiveFieldsIds.id) String? id, 14 | @HiveField(QuestionInfoHiveFieldsIds.number) String? number, 15 | @HiveField(QuestionInfoHiveFieldsIds.url) String? url, 16 | @HiveField(QuestionInfoHiveFieldsIds.tourInfo) TourInfoHiveModel? tourInfo, 17 | }) = _QuestionInfoHiveModel; 18 | } 19 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/models/question_sections/question_section.dart: -------------------------------------------------------------------------------- 1 | abstract class QuestionSectionHiveModel { 2 | String get value; 3 | } 4 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/models/question_sections/section_audio.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:hive/hive.dart'; 3 | import 'package:www_local_storage/src/hive/hive_constants.dart'; 4 | import 'package:www_local_storage/src/hive/models/question_sections/question_section.dart'; 5 | 6 | part 'section_audio.freezed.dart'; 7 | part 'section_audio.g.dart'; 8 | 9 | @freezed 10 | class AudioSectionHiveModel 11 | with _$AudioSectionHiveModel 12 | implements QuestionSectionHiveModel { 13 | @HiveType(typeId: HiveTypesIds.hiveAudioSectionTypeId) 14 | const factory AudioSectionHiveModel({ 15 | @HiveField(AudioSectionHiveFieldsIds.value) required String value, 16 | }) = _AudioSectionHiveModel; 17 | } 18 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/models/question_sections/section_giveaway.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:hive/hive.dart'; 3 | import 'package:www_local_storage/src/hive/hive_constants.dart'; 4 | import 'package:www_local_storage/src/hive/models/question_sections/question_section.dart'; 5 | 6 | part 'section_giveaway.freezed.dart'; 7 | part 'section_giveaway.g.dart'; 8 | 9 | @freezed 10 | class GiveAwaySectionHiveModel 11 | with _$GiveAwaySectionHiveModel 12 | implements QuestionSectionHiveModel { 13 | @HiveType(typeId: HiveTypesIds.hiveGiveAwaySectionTypeId) 14 | const factory GiveAwaySectionHiveModel({ 15 | @HiveField(GiveAwaySectionHiveFieldsIds.value) required String value, 16 | }) = _GiveAwaySectionHiveModel; 17 | } 18 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/models/question_sections/section_image.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:hive/hive.dart'; 3 | import 'package:www_local_storage/src/hive/hive_constants.dart'; 4 | import 'package:www_local_storage/src/hive/models/question_sections/question_section.dart'; 5 | 6 | part 'section_image.g.dart'; 7 | part 'section_image.freezed.dart'; 8 | 9 | @freezed 10 | class ImageSectionHiveModel 11 | with _$ImageSectionHiveModel 12 | implements QuestionSectionHiveModel { 13 | @HiveType(typeId: HiveTypesIds.hiveImageSectionTypeId) 14 | const factory ImageSectionHiveModel({ 15 | @HiveField(ImageSectionHiveFieldsIds.value) required String value, 16 | }) = _ImageSectionHiveModel; 17 | } 18 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/models/question_sections/section_speaker_note.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:hive/hive.dart'; 3 | import 'package:www_local_storage/src/hive/hive_constants.dart'; 4 | import 'package:www_local_storage/src/hive/models/question_sections/question_section.dart'; 5 | 6 | part 'section_speaker_note.freezed.dart'; 7 | part 'section_speaker_note.g.dart'; 8 | 9 | @freezed 10 | class SpeakerNoteSectionHiveModel 11 | with _$SpeakerNoteSectionHiveModel 12 | implements QuestionSectionHiveModel { 13 | @HiveType(typeId: HiveTypesIds.hiveSpeakerNoteSectionTypeId) 14 | const factory SpeakerNoteSectionHiveModel({ 15 | @HiveField(SpeakerNoteSectionHiveFieldsIds.value) required String value, 16 | }) = _SpeakerNoteSectionHiveModel; 17 | } 18 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/models/question_sections/section_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:hive/hive.dart'; 3 | import 'package:www_local_storage/src/hive/hive_constants.dart'; 4 | import 'package:www_local_storage/src/hive/models/question_sections/question_section.dart'; 5 | 6 | part 'section_text.freezed.dart'; 7 | part 'section_text.g.dart'; 8 | 9 | @freezed 10 | class TextSectionHiveModel 11 | with _$TextSectionHiveModel 12 | implements QuestionSectionHiveModel { 13 | @HiveType(typeId: HiveTypesIds.hiveTextSectionTypeId) 14 | const factory TextSectionHiveModel({ 15 | @HiveField(TextSectionHiveFieldsIds.value) required String value, 16 | }) = _TextSectionHiveModel; 17 | } 18 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/models/tour.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:hive/hive.dart'; 3 | import 'package:www_local_storage/src/hive/hive_constants.dart'; 4 | import 'package:www_local_storage/src/hive/models/question.dart'; 5 | import 'package:www_local_storage/src/hive/models/tour_info.dart'; 6 | 7 | part 'tour.freezed.dart'; 8 | part 'tour.g.dart'; 9 | 10 | @freezed 11 | class TourHiveModel with _$TourHiveModel { 12 | @HiveType(typeId: HiveTypesIds.hiveTourTypeId) 13 | const factory TourHiveModel({ 14 | @HiveField(TourHiveFieldsIds.id) String? id, 15 | @HiveField(TourHiveFieldsIds.info) TourInfoHiveModel? info, 16 | @HiveField(TourHiveFieldsIds.questions) List? questions, 17 | }) = _TourHiveModel; 18 | } 19 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/src/hive/models/tournament_status.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:hive/hive.dart'; 3 | import 'package:www_local_storage/src/hive/hive_constants.dart'; 4 | 5 | part 'tournament_status.freezed.dart'; 6 | part 'tournament_status.g.dart'; 7 | 8 | @freezed 9 | class TournamentStatusHiveModel with _$TournamentStatusHiveModel { 10 | @HiveType(typeId: HiveTypesIds.hiveTournamentStatusTypeId) 11 | const factory TournamentStatusHiveModel({ 12 | @HiveField(TournamentStatusInfoHiveFieldsIds.isNew) bool? isNew, 13 | @HiveField(TournamentStatusInfoHiveFieldsIds.isBookmarked) 14 | bool? isBookmarked, 15 | }) = _TournamentStatusHiveModel; 16 | } 17 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/lib/www_local_storage.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_local_storage/src/di/di_module.dart'; 2 | export 'package:www_local_storage/src/service/local_storage.dart'; 3 | export 'package:www_local_storage/src/service/tournaments_local_storage.dart'; 4 | -------------------------------------------------------------------------------- /www-app/domain/www_local_storage/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_local_storage 2 | description: A local storage for all www_* packages 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | freezed_annotation: 2.4.1 13 | hive: ^2.2.3 14 | hive_flutter: ^1.1.0 15 | injectable: 2.4.2 16 | www_analytics: 17 | path: ../../utils/www_analytics 18 | www_di: 19 | path: ../../utils/www_di/ 20 | www_models: 21 | path: ../www_models 22 | 23 | dev_dependencies: 24 | build_runner: 2.4.11 25 | freezed: 2.5.2 26 | hive_generator: ^2.0.0 27 | injectable_generator: 2.6.1 28 | www_analysis: 29 | path: ../../utils/www_analysis 30 | -------------------------------------------------------------------------------- /www-app/domain/www_models/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/misc/app_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | enum AppTheme { none, light, dark } 4 | 5 | extension AppThemeX on AppTheme { 6 | ThemeMode toThemeMode() { 7 | switch (this) { 8 | case AppTheme.none: 9 | return ThemeMode.system; 10 | case AppTheme.light: 11 | return ThemeMode.light; 12 | case AppTheme.dark: 13 | return ThemeMode.dark; 14 | default: 15 | return ThemeMode.system; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/misc/search_parameters.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/www_models.dart'; 3 | 4 | part 'search_parameters.freezed.dart'; 5 | 6 | @freezed 7 | class SearchParameters with _$SearchParameters { 8 | const factory SearchParameters({ 9 | @Default('') String query, 10 | @Default(Sorting.relevance) Sorting sorting, 11 | @Default(0) int nextPage, 12 | }) = _SearchParameters; 13 | } 14 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/misc/sorting.dart: -------------------------------------------------------------------------------- 1 | enum Sorting { relevance, date } 2 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/misc/text_scale.dart: -------------------------------------------------------------------------------- 1 | enum TextScale { normal, medium, large } 2 | 3 | extension TextScaleX on TextScale { 4 | double toDouble() { 5 | switch (this) { 6 | case TextScale.normal: 7 | return 1.0; 8 | case TextScale.medium: 9 | return 1.2; 10 | case TextScale.large: 11 | return 1.4; 12 | default: 13 | return 1.0; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/misc/timer_type.dart: -------------------------------------------------------------------------------- 1 | enum TimerType { normal, doublet, blitz } 2 | 3 | class Timers { 4 | Timers._(); 5 | 6 | static final _timerTypeInSeconds = { 7 | TimerType.normal: 60, 8 | TimerType.doublet: 30, 9 | TimerType.blitz: 20, 10 | }; 11 | 12 | static int getSeconds(TimerType type) => _timerTypeInSeconds[type]!; 13 | } 14 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/question.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/question_info.dart'; 3 | import 'package:www_models/src/models/question_sections/question_section.dart'; 4 | 5 | part 'question.freezed.dart'; 6 | 7 | @freezed 8 | class Question with _$Question { 9 | const factory Question({ 10 | String? id, 11 | String? display, 12 | @Default([]) List question, 13 | @Default([]) List answer, 14 | @Default([]) List passCriteria, 15 | @Default([]) List comments, 16 | String? authors, 17 | String? sources, 18 | @Default(QuestionInfo()) QuestionInfo info, 19 | }) = _Question; 20 | } 21 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/question_info.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/tour_info.dart'; 3 | 4 | part 'question_info.freezed.dart'; 5 | 6 | @freezed 7 | class QuestionInfo with _$QuestionInfo { 8 | const factory QuestionInfo({ 9 | String? id, 10 | String? number, 11 | String? url, 12 | @Default(TourInfo()) TourInfo tourInfo, 13 | }) = _QuestionInfo; 14 | } 15 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/question_sections/question_section.dart: -------------------------------------------------------------------------------- 1 | abstract class QuestionSection { 2 | String get value; 3 | } 4 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/question_sections/section_audio.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/question_sections/question_section.dart'; 3 | 4 | part 'section_audio.freezed.dart'; 5 | 6 | @freezed 7 | class AudioSection with _$AudioSection implements QuestionSection { 8 | const factory AudioSection({ 9 | required String value, 10 | }) = _AudioSection; 11 | } 12 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/question_sections/section_giveaway.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/question_sections/question_section.dart'; 3 | 4 | part 'section_giveaway.freezed.dart'; 5 | 6 | @freezed 7 | class GiveAwaySection with _$GiveAwaySection implements QuestionSection { 8 | const factory GiveAwaySection({ 9 | required String value, 10 | }) = _GiveAwaySection; 11 | } 12 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/question_sections/section_image.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/question_sections/question_section.dart'; 3 | 4 | part 'section_image.freezed.dart'; 5 | 6 | @freezed 7 | class ImageSection with _$ImageSection implements QuestionSection { 8 | const factory ImageSection({ 9 | required String value, 10 | }) = _ImageSection; 11 | } 12 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/question_sections/section_speaker_note.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/question_sections/question_section.dart'; 3 | 4 | part 'section_speaker_note.freezed.dart'; 5 | 6 | @freezed 7 | class SpeakerNoteSection with _$SpeakerNoteSection implements QuestionSection { 8 | const factory SpeakerNoteSection({ 9 | required String value, 10 | }) = _SpeakerNoteSection; 11 | } 12 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/question_sections/section_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/question_sections/question_section.dart'; 3 | 4 | part 'section_text.freezed.dart'; 5 | 6 | @freezed 7 | class TextSection with _$TextSection implements QuestionSection { 8 | const factory TextSection({ 9 | required String value, 10 | }) = _TextSection; 11 | } 12 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/random_questions.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/question.dart'; 3 | 4 | part 'random_questions.freezed.dart'; 5 | 6 | @freezed 7 | class RandomQuestions with _$RandomQuestions { 8 | const factory RandomQuestions({ 9 | @Default([]) List questions, 10 | }) = _RandomQuestions; 11 | } 12 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/tour.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/question.dart'; 3 | import 'package:www_models/src/models/tour_info.dart'; 4 | 5 | part 'tour.freezed.dart'; 6 | 7 | @freezed 8 | class Tour with _$Tour { 9 | const factory Tour({ 10 | String? id, 11 | @Default(TourInfo()) TourInfo info, 12 | @Default([]) List questions, 13 | }) = _Tour; 14 | } 15 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/tour_info.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/tournament_info.dart'; 3 | 4 | part 'tour_info.freezed.dart'; 5 | 6 | @freezed 7 | class TourInfo with _$TourInfo { 8 | const factory TourInfo({ 9 | String? id, 10 | String? title, 11 | String? questionsCount, 12 | String? description, 13 | String? url, 14 | String? editors, 15 | String? createdAt, 16 | String? playedAt, 17 | @Default(TournamentInfo()) TournamentInfo tournamentInfo, 18 | }) = _TourInfo; 19 | } 20 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/tournament.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartx/dartx.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_models/src/models/tour.dart'; 4 | import 'package:www_models/src/models/tournament_info.dart'; 5 | import 'package:www_models/src/models/tournament_status.dart'; 6 | 7 | part 'tournament.freezed.dart'; 8 | 9 | @freezed 10 | class Tournament with _$Tournament { 11 | const factory Tournament({ 12 | String? id, 13 | String? id2, 14 | @Default(TournamentInfo()) TournamentInfo info, 15 | @Default(TournamentStatus()) TournamentStatus status, 16 | @Default([]) List tours, 17 | }) = _Tournament; 18 | } 19 | 20 | extension TournamentX on Tournament { 21 | bool isTheOne(TournamentInfo info) => 22 | (info.id.isNotNullOrEmpty && this.id == info.id) || 23 | (info.id2.isNotNullOrEmpty && this.id2 == info.id2); 24 | } 25 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/tournament_info.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | 3 | part 'tournament_info.freezed.dart'; 4 | 5 | @freezed 6 | class TournamentInfo with _$TournamentInfo { 7 | const factory TournamentInfo({ 8 | String? id, 9 | String? id2, 10 | String? title, 11 | String? questionsCount, 12 | String? toursCount, 13 | String? description, 14 | String? url, 15 | String? editors, 16 | String? createdAt, 17 | String? playedAt, 18 | }) = _TournamentInfo; 19 | } 20 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/tournament_status.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | 3 | part 'tournament_status.freezed.dart'; 4 | 5 | @freezed 6 | class TournamentStatus with _$TournamentStatus { 7 | const factory TournamentStatus({ 8 | @Default(false) bool isNew, 9 | @Default(false) bool isBookmarked, 10 | }) = _TournamentStatus; 11 | } 12 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/tournaments_tree.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | import 'package:www_models/src/models/tournaments_tree_info.dart'; 3 | 4 | part 'tournaments_tree.freezed.dart'; 5 | 6 | @freezed 7 | class TournamentsTree with _$TournamentsTree { 8 | const factory TournamentsTree({ 9 | String? id, 10 | @Default([]) List children, 11 | @Default(TournamentsTreeInfo()) TournamentsTreeInfo info, 12 | }) = _TournamentsTree; 13 | } 14 | -------------------------------------------------------------------------------- /www-app/domain/www_models/lib/src/models/tournaments_tree_info.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | 3 | part 'tournaments_tree_info.freezed.dart'; 4 | 5 | @freezed 6 | class TournamentsTreeInfo with _$TournamentsTreeInfo { 7 | const factory TournamentsTreeInfo({ 8 | String? id, 9 | String? title, 10 | String? childrenCount, 11 | }) = _TournamentsTreeInfo; 12 | } 13 | -------------------------------------------------------------------------------- /www-app/domain/www_models/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_models 2 | description: www_* models 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | dartx: ^1.2.0 11 | flutter: 12 | sdk: flutter 13 | freezed_annotation: 2.4.1 14 | 15 | dev_dependencies: 16 | build_runner: 2.4.11 17 | freezed: 2.5.2 18 | www_analysis: 19 | path: ../../utils/www_analysis 20 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_redux_actions/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/shared/www_redux_actions/lib/src/browse_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_models/www_models.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | 6 | part 'browse_actions.freezed.dart'; 7 | 8 | abstract class BrowseAction implements IAction {} 9 | 10 | @freezed 11 | class UserActionBrowse 12 | with _$UserActionBrowse 13 | implements BrowseAction, IUserAction { 14 | const factory UserActionBrowse.database() = DatabaseBrowseUserAction; 15 | 16 | const factory UserActionBrowse.question({ 17 | required QuestionInfo info, 18 | }) = QuestionBrowseUserAction; 19 | 20 | const factory UserActionBrowse.tour({ 21 | required TourInfo info, 22 | }) = TourBrowseUserAction; 23 | 24 | const factory UserActionBrowse.tournament({ 25 | required TournamentInfo info, 26 | }) = TournamentBrowseUserAction; 27 | 28 | const factory UserActionBrowse.uri({ 29 | required String uri, 30 | }) = UriBrowseUserAction; 31 | } 32 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_redux_actions/lib/src/developer_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_localization/www_localization.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | 6 | part 'developer_actions.freezed.dart'; 7 | 8 | abstract class DeveloperAction implements IAction {} 9 | 10 | @freezed 11 | class UserActionDeveloper 12 | with _$UserActionDeveloper 13 | implements DeveloperAction, IUserAction { 14 | const factory UserActionDeveloper.email({ 15 | required Translations translations, 16 | }) = EmailDeveloperUserAction; 17 | 18 | const factory UserActionDeveloper.visitWebsite() = 19 | VisitWebsiteDeveloperUserAction; 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_redux_actions/lib/src/dialogs_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_models/www_models.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | 6 | part 'dialogs_actions.freezed.dart'; 7 | 8 | abstract class DialogAction implements IAction {} 9 | 10 | @freezed 11 | class UserActionDialog 12 | with _$UserActionDialog 13 | implements DialogAction, IUserAction { 14 | const factory UserActionDialog.tourInfo({ 15 | required TourInfo info, 16 | }) = TourInfoDialogUserAction; 17 | 18 | const factory UserActionDialog.tournamentInfo({ 19 | required TournamentInfo info, 20 | }) = TournamentInfoDialogUserAction; 21 | } 22 | 23 | @freezed 24 | class SystemActionDialog 25 | with _$SystemActionDialog 26 | implements DialogAction, ISystemAction { 27 | const factory SystemActionDialog.rating() = RatingDialogSystemAction; 28 | } 29 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_redux_actions/lib/src/initialization_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | 5 | part 'initialization_actions.freezed.dart'; 6 | 7 | @freezed 8 | class InitializationAction 9 | with _$InitializationAction 10 | implements IAction, ISystemAction { 11 | const factory InitializationAction.initCore() = InitCoreInitializationAction; 12 | 13 | const factory InitializationAction.initServices() = 14 | InitServicesInitializationAction; 15 | 16 | const factory InitializationAction.initSettings() = 17 | InitSettingsInitializationAction; 18 | 19 | const factory InitializationAction.failed({required Exception exception}) = 20 | FailedInitializationAction; 21 | 22 | const factory InitializationAction.completed() = 23 | CompletedInitializationAction; 24 | } 25 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_redux_actions/lib/src/rating_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | 5 | part 'rating_actions.freezed.dart'; 6 | 7 | abstract class RatingAction implements IAction {} 8 | 9 | @freezed 10 | class UserActionRating 11 | with _$UserActionRating 12 | implements RatingAction, IUserAction { 13 | const factory UserActionRating.rate({ 14 | required int rating, 15 | }) = RateRatingUserAction; 16 | 17 | const factory UserActionRating.neverAsk() = NeverAskRatingUserAction; 18 | } 19 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_redux_actions/lib/src/services_actions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | 5 | part 'services_actions.freezed.dart'; 6 | 7 | abstract class ServicesAction implements IAction {} 8 | 9 | @freezed 10 | class SystemActionServices 11 | with _$SystemActionServices 12 | implements ServicesAction, ISystemAction { 13 | const factory SystemActionServices.coreReady() = 14 | CoreReadyServicesSystemAction; 15 | 16 | const factory SystemActionServices.servicesReady() = 17 | ServicesReadyServicesSystemAction; 18 | } 19 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_redux_actions/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_redux_actions 2 | description: Redux actions for the entire WWW app 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | freezed_annotation: 2.4.1 13 | www_localization: 14 | path: ../../../core/www_localization 15 | www_models: 16 | path: ../../../domain/www_models 17 | www_redux: 18 | path: ../../../utils/www_redux 19 | 20 | dev_dependencies: 21 | build_runner: 2.4.11 22 | freezed: 2.5.2 23 | www_analysis: 24 | path: ../../../utils/www_analysis 25 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_tournament_status/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/shared/www_tournament_status/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_tournament_status/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleTournamentStatus extends WWWDIModule { 7 | const WWWDIModuleTournamentStatus() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_tournament_status/lib/www_tournament_status.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_tournament_status/src/di/di_module.dart'; 2 | export 'package:www_tournament_status/src/service/tournament_status.dart'; 3 | export 'package:www_tournament_status/src/service/tournaments_bookmarks.dart'; 4 | export 'package:www_tournament_status/src/service/tournaments_history.dart'; 5 | -------------------------------------------------------------------------------- /www-app/feature/shared/www_tournament_status/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_tournament_status 2 | description: Tournaments history and bookmark status 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | injectable: 2.4.2 13 | www_di: 14 | path: ../../../utils/www_di/ 15 | www_local_storage: 16 | path: ../../../domain/www_local_storage 17 | www_models: 18 | path: ../../../domain/www_models 19 | www_utils: 20 | path: ../../../utils/www_utils 21 | 22 | dev_dependencies: 23 | build_runner: 2.4.11 24 | injectable_generator: 2.6.1 25 | www_analysis: 26 | path: ../../../utils/www_analysis 27 | -------------------------------------------------------------------------------- /www-app/feature/www_about/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_about/lib/www_about.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_about/src/presentation/route_page.dart'; 2 | -------------------------------------------------------------------------------- /www-app/feature/www_about/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_about 2 | description: About the app feature 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | flutter_svg: ^2.0.7 13 | www_constants: 14 | path: ../../core/www_constants 15 | www_localization: 16 | path: ../../core/www_localization 17 | www_redux: 18 | path: ../../utils/www_redux 19 | www_redux_actions: 20 | path: ../shared/www_redux_actions 21 | www_theme: 22 | path: ../../design/www_theme 23 | 24 | dev_dependencies: 25 | www_analysis: 26 | path: ../../utils/www_analysis 27 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_bookmarks/src/di/di_module.config.dart'; 4 | import 'package:www_di/www_di.dart'; 5 | 6 | class WWWDIModuleBookmarks extends WWWDIModule { 7 | const WWWDIModuleBookmarks() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/src/presentation/app_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_localization/www_localization.dart'; 3 | import 'package:www_theme/www_theme.dart'; 4 | 5 | class BookmarksPageAppBar extends StatelessWidget { 6 | const BookmarksPageAppBar({Key? key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) => SliverAppBar( 10 | title: Text(context.translations.bookmarksPageTitle), 11 | iconTheme: context 12 | .styleConfig.tournamentsTreeStyleConfiguration.appBarIconTheme, 13 | floating: true, 14 | snap: true, 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/src/presentation/data_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_bookmarks/src/presentation/empty_bookmarks.dart'; 3 | import 'package:www_models/www_models.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | import 'package:www_redux_actions/www_redux_actions.dart'; 6 | import 'package:www_widgets/www_widgets.dart'; 7 | 8 | class BookmarksDataPage extends StatelessWidget { 9 | const BookmarksDataPage({Key? key, required this.data}) : super(key: key); 10 | 11 | final List data; 12 | 13 | @override 14 | Widget build(BuildContext context) => data.isNotEmpty 15 | ? TournamentsGrid( 16 | tournaments: data, 17 | onItemTap: (tournament) => context.dispatch(UserActionTournament.open( 18 | info: tournament.info, 19 | status: tournament.status, 20 | )), 21 | ) 22 | : const EmptyBookmarks(); 23 | } 24 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/src/presentation/empty_bookmarks.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_localization/www_localization.dart'; 3 | import 'package:www_theme/www_theme.dart'; 4 | 5 | class EmptyBookmarks extends StatelessWidget { 6 | const EmptyBookmarks({Key? key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) => SliverFillRemaining( 10 | hasScrollBody: false, 11 | child: Padding( 12 | padding: Dimensions.defaultPadding * 2, 13 | child: Center( 14 | child: Text( 15 | context.translations.bookmarksEmptyMessage, 16 | textAlign: TextAlign.center, 17 | style: Theme.of(context).textTheme.titleMedium!.copyWith( 18 | color: context 19 | .styleConfig.bookmarksStyleConfiguration.errorColor, 20 | ), 21 | ), 22 | ), 23 | ), 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/src/presentation/error_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_redux_actions/www_redux_actions.dart'; 4 | import 'package:www_theme/www_theme.dart'; 5 | import 'package:www_widgets/www_widgets.dart'; 6 | 7 | class BookmarksErrorPage extends StatelessWidget { 8 | const BookmarksErrorPage({ 9 | Key? key, 10 | required this.exception, 11 | }) : super(key: key); 12 | 13 | final Exception exception; 14 | 15 | @override 16 | Widget build(BuildContext context) => SliverFillRemaining( 17 | hasScrollBody: false, 18 | child: ErrorMessage( 19 | exception: exception, 20 | retryFunction: () => _reload(context), 21 | color: context.styleConfig.bookmarksStyleConfiguration.errorColor, 22 | ), 23 | ); 24 | 25 | void _reload(BuildContext context) => 26 | context.dispatch(const UserActionBookmarks.load()); 27 | } 28 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/src/presentation/loading_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_theme/www_theme.dart'; 3 | import 'package:www_widgets/www_widgets.dart'; 4 | 5 | class BookmarksLoadingPage extends StatelessWidget { 6 | const BookmarksLoadingPage({Key? key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) => TournamentsGrid( 10 | stubTournamentsCount: context 11 | .styleConfig.bookmarksStyleConfiguration.stubTournamentsCount, 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/src/presentation/route_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_bookmarks/src/presentation/app_bar.dart'; 3 | import 'package:www_bookmarks/src/presentation/page_content.dart'; 4 | import 'package:www_theme/www_theme.dart'; 5 | import 'package:www_widgets/www_widgets.dart'; 6 | 7 | class BookmarksRoutePage extends StatelessWidget { 8 | const BookmarksRoutePage({Key? key}) : super(key: key); 9 | 10 | static const String routeName = 'bookmarks'; 11 | 12 | @override 13 | Widget build(BuildContext context) => WWWStatusBarBrightness( 14 | statusBarBrightness: Brightness.light, 15 | child: Scaffold( 16 | backgroundColor: context 17 | .styleConfig.bookmarksStyleConfiguration.scaffoldBackground, 18 | body: const CustomScrollView( 19 | physics: BouncingScrollPhysics(), 20 | slivers: [ 21 | BookmarksPageAppBar(), 22 | BookmarksPageContent(), 23 | ], 24 | ), 25 | ), 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/src/redux/state.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:flutter/foundation.dart'; 3 | import 'package:freezed_annotation/freezed_annotation.dart'; 4 | import 'package:www_models/www_models.dart'; 5 | import 'package:www_redux/www_redux.dart'; 6 | 7 | part 'state.freezed.dart'; 8 | 9 | @freezed 10 | class BookmarksState with _$BookmarksState implements IState { 11 | const factory BookmarksState.initial() = InitialBookmarksState; 12 | 13 | const factory BookmarksState.data({ 14 | required List data, 15 | }) = DataBookmarksState; 16 | 17 | const factory BookmarksState.loading() = LoadingBookmarksState; 18 | 19 | const factory BookmarksState.error({ 20 | required Exception exception, 21 | }) = ErrorBookmarksState; 22 | } 23 | 24 | extension BookmarksStateX on BookmarksState { 25 | Option> get dataOption => optionOf(this.maybeMap( 26 | data: (value) => value.data, 27 | orElse: () => null, 28 | )); 29 | } 30 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_bookmarks/src/redux/state.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | 5 | abstract class IBookmarksStateHolder implements IState { 6 | Option get bookmarksState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_bookmarks/lib/www_bookmarks.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_bookmarks/src/di/di_module.dart'; 2 | export 'package:www_bookmarks/src/presentation/route_page.dart'; 3 | export 'package:www_bookmarks/src/redux/middleware.dart'; 4 | export 'package:www_bookmarks/src/redux/reducer.dart'; 5 | export 'package:www_bookmarks/src/redux/state.dart'; 6 | export 'package:www_bookmarks/src/redux/state_holder.dart'; 7 | -------------------------------------------------------------------------------- /www-app/feature/www_browsing/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_browsing/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_browsing/src/di/di_module.config.dart'; 4 | import 'package:www_di/www_di.dart'; 5 | 6 | class WWWDIModuleBrowsing extends WWWDIModule { 7 | const WWWDIModuleBrowsing() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_browsing/lib/www_browsing.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_browsing/src/di/di_module.dart'; 2 | export 'package:www_browsing/src/redux/middleware.dart'; 3 | -------------------------------------------------------------------------------- /www-app/feature/www_browsing/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_browsing 2 | description: An open-in-browser feature 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | injectable: 2.4.2 13 | url_launcher: ^6.1.12 14 | www_analytics: 15 | path: ../../utils/www_analytics 16 | www_constants: 17 | path: ../../core/www_constants 18 | www_di: 19 | path: ../../utils/www_di 20 | www_redux: 21 | path: ../../utils/www_redux 22 | www_redux_actions: 23 | path: ../shared/www_redux_actions 24 | 25 | dev_dependencies: 26 | build_runner: 2.4.11 27 | injectable_generator: 2.6.1 28 | www_analysis: 29 | path: ../../utils/www_analysis 30 | -------------------------------------------------------------------------------- /www-app/feature/www_image_details/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_image_details/lib/www_image_details.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_image_details/src/presentation/route_page.dart'; 2 | -------------------------------------------------------------------------------- /www-app/feature/www_image_details/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_image_details 2 | description: Zoomed-in image page 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | cached_network_image: ^3.2.3 11 | flutter: 12 | sdk: flutter 13 | photo_view: ^0.14.0 14 | www_theme: 15 | path: ../../design/www_theme 16 | 17 | dev_dependencies: 18 | www_analysis: 19 | path: ../../utils/www_analysis 20 | -------------------------------------------------------------------------------- /www-app/feature/www_initialization/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_initialization/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_initialization/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleInitialization extends WWWDIModule { 7 | const WWWDIModuleInitialization() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_initialization/lib/src/redux/state.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | 5 | part 'state.freezed.dart'; 6 | 7 | @freezed 8 | class InitializationState with _$InitializationState implements IState { 9 | const factory InitializationState.completed() = _CompletedInitializationState; 10 | 11 | const factory InitializationState.inProgress({ 12 | @Default(false) bool coreReady, 13 | @Default(false) bool settingsReady, 14 | @Default(false) bool servicesReady, 15 | }) = _InProgressInitializationState; 16 | 17 | const factory InitializationState.failed() = _FailedInitializationState; 18 | } 19 | -------------------------------------------------------------------------------- /www-app/feature/www_initialization/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_initialization/src/redux/state.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | 5 | abstract class IInitializationStateHolder implements IState { 6 | Option get initializationState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_initialization/lib/www_initialization.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_initialization/src/di/di_module.dart'; 2 | export 'package:www_initialization/src/redux/middleware.dart'; 3 | export 'package:www_initialization/src/redux/reducer.dart'; 4 | export 'package:www_initialization/src/redux/state.dart'; 5 | export 'package:www_initialization/src/redux/state_holder.dart'; 6 | -------------------------------------------------------------------------------- /www-app/feature/www_initialization/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_initialization 2 | description: App initialization 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | dartx: ^1.2.0 11 | flutter: 12 | sdk: flutter 13 | freezed_annotation: 2.4.1 14 | injectable: 2.4.2 15 | www_analytics: 16 | path: ../../utils/www_analytics 17 | www_background_runner: 18 | path: ../../utils/www_background_runner 19 | www_cache: 20 | path: ../../domain/www_cache 21 | www_di: 22 | path: ../../utils/www_di 23 | www_local_storage: 24 | path: ../../domain/www_local_storage 25 | www_redux: 26 | path: ../../utils/www_redux 27 | www_redux_actions: 28 | path: ../shared/www_redux_actions 29 | www_timer: 30 | path: ../www_timer 31 | 32 | dev_dependencies: 33 | build_runner: 2.4.11 34 | flutter_test: 35 | sdk: flutter 36 | freezed: 2.5.2 37 | injectable_generator: 2.6.1 38 | www_analysis: 39 | path: ../../utils/www_analysis 40 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_latest_tournaments/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleLatestTournaments extends WWWDIModule { 7 | const WWWDIModuleLatestTournaments() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/app_bar_buttons/bookmarks.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_custom_icons/www_custom_icons.dart'; 3 | import 'package:www_localization/www_localization.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | import 'package:www_redux_actions/www_redux_actions.dart'; 6 | 7 | class LatestTournamentsAppBarBookmarksButton extends StatelessWidget { 8 | const LatestTournamentsAppBarBookmarksButton({Key? key}) : super(key: key); 9 | 10 | @override 11 | Widget build(BuildContext context) => IconButton( 12 | icon: const Icon(WWWCustomIcons.bookmarks), 13 | tooltip: context.translations.tooltipBookmarks, 14 | onPressed: () => _openRandomQuestions(context), 15 | ); 16 | 17 | void _openRandomQuestions(BuildContext context) => 18 | context.dispatch(const UserActionBookmarks.open()); 19 | } 20 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/app_bar_buttons/more.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_latest_tournaments/src/presentation/bottom_sheet/bottom_sheet.dart'; 3 | 4 | class LatestTournamentsAppBarMoreButton extends StatelessWidget { 5 | const LatestTournamentsAppBarMoreButton({Key? key}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) => IconButton( 9 | icon: const Icon(Icons.more_vert), 10 | onPressed: () => _showMenu(context), 11 | ); 12 | 13 | void _showMenu(BuildContext context) => showModalBottomSheet( 14 | context: context, 15 | builder: (context) => const LatestTournamentsBottomSheet(), 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/app_bar_buttons/random.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_custom_icons/www_custom_icons.dart'; 3 | import 'package:www_localization/www_localization.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | import 'package:www_redux_actions/www_redux_actions.dart'; 6 | 7 | class LatestTournamentsAppBarRandomButton extends StatelessWidget { 8 | const LatestTournamentsAppBarRandomButton({Key? key}) : super(key: key); 9 | 10 | @override 11 | Widget build(BuildContext context) => IconButton( 12 | icon: const Icon(WWWCustomIcons.random_card), 13 | tooltip: context.translations.tooltipRandomQuestions, 14 | onPressed: () => _openRandomQuestions(context), 15 | ); 16 | 17 | void _openRandomQuestions(BuildContext context) => 18 | context.dispatch(const UserActionQuestions.openRandom()); 19 | } 20 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/bottom_sheet/bottom_sheet.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_latest_tournaments/src/presentation/bottom_sheet/items/about.dart'; 3 | import 'package:www_latest_tournaments/src/presentation/bottom_sheet/items/search.dart'; 4 | import 'package:www_latest_tournaments/src/presentation/bottom_sheet/items/settings.dart'; 5 | import 'package:www_latest_tournaments/src/presentation/bottom_sheet/items/tree.dart'; 6 | import 'package:www_widgets/www_widgets.dart'; 7 | 8 | class LatestTournamentsBottomSheet extends StatelessWidget { 9 | const LatestTournamentsBottomSheet({Key? key}) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) => const ModalBottomSheetContainer( 13 | children: [ 14 | LatestTournamentsSearchBottomSheetItem(), 15 | LatestTournamentsTreeBottomSheetItem(), 16 | LatestTournamentsSettingsBottomSheetItem(), 17 | LatestTournamentsAboutBottomSheetItem(), 18 | ], 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/bottom_sheet/items/about.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_localization/www_localization.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | import 'package:www_redux_actions/www_redux_actions.dart'; 5 | 6 | class LatestTournamentsAboutBottomSheetItem extends StatelessWidget { 7 | const LatestTournamentsAboutBottomSheetItem({Key? key}) : super(key: key); 8 | 9 | @override 10 | Widget build(BuildContext context) => ListTile( 11 | leading: const Icon(Icons.info_outline), 12 | title: Text(context.translations.menuAbout), 13 | onTap: () { 14 | Navigator.pop(context); 15 | 16 | context.dispatch(const UserActionNavigation.about()); 17 | }, 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/bottom_sheet/items/search.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_localization/www_localization.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | import 'package:www_redux_actions/www_redux_actions.dart'; 5 | 6 | class LatestTournamentsSearchBottomSheetItem extends StatelessWidget { 7 | const LatestTournamentsSearchBottomSheetItem({Key? key}) : super(key: key); 8 | 9 | @override 10 | Widget build(BuildContext context) => ListTile( 11 | leading: const Icon(Icons.search), 12 | title: Text(context.translations.menuTournamentsSearch), 13 | onTap: () { 14 | Navigator.pop(context); 15 | 16 | context.dispatch(const UserActionSearch.open()); 17 | }, 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/bottom_sheet/items/settings.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_custom_icons/www_custom_icons.dart'; 3 | import 'package:www_localization/www_localization.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | import 'package:www_redux_actions/www_redux_actions.dart'; 6 | 7 | class LatestTournamentsSettingsBottomSheetItem extends StatelessWidget { 8 | const LatestTournamentsSettingsBottomSheetItem({Key? key}) : super(key: key); 9 | 10 | @override 11 | Widget build(BuildContext context) => ListTile( 12 | leading: const Icon(WWWCustomIcons.settings), 13 | title: Text(context.translations.menuSettings), 14 | onTap: () { 15 | Navigator.pop(context); 16 | 17 | context.dispatch(const UserActionSettings.open()); 18 | }, 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/bottom_sheet/items/tree.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_custom_icons/www_custom_icons.dart'; 3 | import 'package:www_localization/www_localization.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | import 'package:www_redux_actions/www_redux_actions.dart'; 6 | 7 | class LatestTournamentsTreeBottomSheetItem extends StatelessWidget { 8 | const LatestTournamentsTreeBottomSheetItem({Key? key}) : super(key: key); 9 | 10 | @override 11 | Widget build(BuildContext context) => ListTile( 12 | leading: const Icon(WWWCustomIcons.tree), 13 | title: Text(context.translations.menuTournamentsTree), 14 | onTap: () { 15 | Navigator.pop(context); 16 | 17 | context.dispatch(const UserActionTournamentsTree.open()); 18 | }, 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/error_message.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_redux_actions/www_redux_actions.dart'; 4 | import 'package:www_theme/www_theme.dart'; 5 | import 'package:www_widgets/www_widgets.dart'; 6 | 7 | class LatestTournamentsErrorMessage extends StatelessWidget { 8 | const LatestTournamentsErrorMessage({ 9 | Key? key, 10 | this.dense = false, 11 | this.exception, 12 | }) : super(key: key); 13 | 14 | final bool dense; 15 | final Exception? exception; 16 | 17 | @override 18 | Widget build(BuildContext context) => ErrorMessage( 19 | exception: exception, 20 | retryFunction: () => _reload(context), 21 | color: 22 | context.styleConfig.latestTournamentsStyleConfiguration.errorColor, 23 | dense: dense, 24 | ); 25 | 26 | void _reload(BuildContext context) => 27 | context.dispatch(const UserActionLatest.load()); 28 | } 29 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/presentation/loading_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_theme/www_theme.dart'; 3 | import 'package:www_widgets/www_widgets.dart'; 4 | 5 | class LatestTournamentsLoadingPage extends StatelessWidget { 6 | const LatestTournamentsLoadingPage({Key? key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) => TournamentsGrid( 10 | stubTournamentsCount: context.styleConfig 11 | .latestTournamentsStyleConfiguration.stubTournamentsCount, 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_latest_tournaments/src/redux/state.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | 5 | abstract class ILatestTournamentsStateHolder implements IState { 6 | Option get latestTournamentsState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/lib/www_latest_tournaments.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_latest_tournaments/src/di/di_module.dart'; 2 | export 'package:www_latest_tournaments/src/presentation/route_page.dart'; 3 | export 'package:www_latest_tournaments/src/redux/middleware.dart'; 4 | export 'package:www_latest_tournaments/src/redux/reducer.dart'; 5 | export 'package:www_latest_tournaments/src/redux/state.dart'; 6 | export 'package:www_latest_tournaments/src/redux/state_holder.dart'; 7 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/test/mocks/mocks.dart: -------------------------------------------------------------------------------- 1 | import 'package:mocktail/mocktail.dart'; 2 | import 'package:www_analytics/www_analytics.dart'; 3 | import 'package:www_api/www_api.dart'; 4 | import 'package:www_tournament_status/www_tournament_status.dart'; 5 | 6 | class MockLatestTournamentsLoader extends Mock 7 | implements ILatestTournamentsLoader {} 8 | 9 | class MockTournamentStatusService extends Mock 10 | implements ITournamentStatusService {} 11 | 12 | class MockCrashWrapper extends Mock implements ICrashWrapper {} 13 | -------------------------------------------------------------------------------- /www-app/feature/www_latest_tournaments/test/service/latest_tournaments_provider/test_data_1.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_models/www_models.dart'; 2 | 3 | const expectedTournaments1 = [ 4 | Tournament( 5 | id2: '1', 6 | info: TournamentInfo( 7 | id2: '1', 8 | ), 9 | ), 10 | Tournament( 11 | id2: '2', 12 | info: TournamentInfo( 13 | id2: '2', 14 | ), 15 | ), 16 | ]; 17 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_questions/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleQuestions extends WWWDIModule { 7 | const WWWDIModuleQuestions() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/presentation/app_bar/bottom_app_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_questions/src/presentation/app_bar/buttons/more.dart'; 3 | import 'package:www_questions/src/presentation/app_bar/timer_text.dart'; 4 | import 'package:www_theme/www_theme.dart'; 5 | 6 | class QuestionsBottomAppBar extends StatelessWidget { 7 | const QuestionsBottomAppBar({Key? key}) : super(key: key); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | final styleConfiguration = context.styleConfig.questionStyleConfiguration; 12 | 13 | return BottomAppBar( 14 | notchMargin: styleConfiguration.bottomAppBarNotchMargin, 15 | child: IconTheme( 16 | data: styleConfiguration.bottomAppBarIconTheme, 17 | child: const Row( 18 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 19 | children: [ 20 | QuestionsBottomAppBarTimerText(), 21 | QuestionsBottomAppBarMoreButton(), 22 | ], 23 | ), 24 | ), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/presentation/app_bar/buttons/more.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_questions/src/presentation/bottom_sheet/bottom_sheet.dart'; 3 | 4 | class QuestionsBottomAppBarMoreButton extends StatelessWidget { 5 | const QuestionsBottomAppBarMoreButton({Key? key}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) => IconButton( 9 | icon: const Icon(Icons.more_vert), 10 | onPressed: () => _showMenu(context), 11 | ); 12 | 13 | void _showMenu(BuildContext context) => showModalBottomSheet( 14 | context: context, 15 | builder: (context) => const QuestionsBottomSheet(), 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/presentation/bottom_sheet/bottom_sheet.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_questions/src/presentation/bottom_sheet/items/about.dart'; 3 | import 'package:www_questions/src/presentation/bottom_sheet/items/browse.dart'; 4 | import 'package:www_questions/src/presentation/bottom_sheet/items/share.dart'; 5 | import 'package:www_widgets/www_widgets.dart'; 6 | 7 | class QuestionsBottomSheet extends StatelessWidget { 8 | const QuestionsBottomSheet({Key? key}) : super(key: key); 9 | 10 | @override 11 | Widget build(BuildContext context) => const ModalBottomSheetContainer( 12 | children: [ 13 | QuestionsBrowseBottomSheetItem(), 14 | QuestionsShareBottomSheetItem(), 15 | QuestionsAboutTourBottomSheetItem(), 16 | ], 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/presentation/error_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_redux_actions/www_redux_actions.dart'; 4 | import 'package:www_theme/www_theme.dart'; 5 | import 'package:www_widgets/www_widgets.dart'; 6 | 7 | class QuestionsErrorPage extends StatelessWidget { 8 | const QuestionsErrorPage({ 9 | Key? key, 10 | this.exception, 11 | }) : super(key: key); 12 | 13 | final Exception? exception; 14 | 15 | @override 16 | Widget build(BuildContext context) => ErrorMessage( 17 | exception: exception, 18 | retryFunction: () => _reload(context), 19 | color: context.styleConfig.questionStyleConfiguration.errorColor, 20 | ); 21 | 22 | void _reload(BuildContext context) => 23 | context.dispatch(const UserActionQuestions.loadRandom()); 24 | } 25 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/presentation/loading_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_questions/src/presentation/questions_cards.dart'; 3 | import 'package:www_theme/www_theme.dart'; 4 | 5 | class QuestionsLoadingPage extends StatelessWidget { 6 | const QuestionsLoadingPage({Key? key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) => QuestionsCards( 10 | stubQuestionsCount: 11 | context.styleConfig.questionStyleConfiguration.stubQuestionsCount, 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/presentation/question/question_number.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_localization/www_localization.dart'; 3 | import 'package:www_theme/www_theme.dart'; 4 | 5 | class QuestionNumber extends StatelessWidget { 6 | const QuestionNumber({ 7 | Key? key, 8 | this.number, 9 | }) : super(key: key); 10 | 11 | final String? number; 12 | 13 | @override 14 | Widget build(BuildContext context) => Text( 15 | '${context.translations.questionNumber} ${number ?? ''}', 16 | style: context 17 | .styleConfig.questionStyleConfiguration.questionCardTitleTextStyle, 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/presentation/question/question_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_models/www_models.dart'; 3 | import 'package:www_questions/src/presentation/question/question_sections.dart'; 4 | import 'package:www_theme/www_theme.dart'; 5 | 6 | class QuestionText extends StatelessWidget { 7 | const QuestionText({ 8 | Key? key, 9 | required this.question, 10 | }) : super(key: key); 11 | 12 | final Question question; 13 | 14 | @override 15 | Widget build(BuildContext context) => QuestionTextSectionsTheme( 16 | data: context.styleConfig.questionStyleConfiguration 17 | .questionCardQuestionSectionsThemeData, 18 | child: QuestionSections(sections: question.question), 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/presentation/question/separator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_theme/www_theme.dart'; 3 | 4 | class QuestionsCardSeparator extends StatelessWidget { 5 | const QuestionsCardSeparator({Key? key}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | final styleConfiguration = context.styleConfig.questionStyleConfiguration; 10 | 11 | return Divider( 12 | height: styleConfiguration.questionCardDividerHeight, 13 | color: styleConfiguration.questionCardDividerColor, 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_questions/src/redux/state.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | 5 | abstract class IQuestionsStateHolder implements IState { 6 | Option get questionsState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/src/service/random_questions_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:www_analytics/www_analytics.dart'; 3 | import 'package:www_api/www_api.dart'; 4 | import 'package:www_models/www_models.dart'; 5 | 6 | abstract class IRandomQuestionsProvider { 7 | Future> get(); 8 | } 9 | 10 | @LazySingleton(as: IRandomQuestionsProvider) 11 | class RandomQuestionsProvider implements IRandomQuestionsProvider { 12 | const RandomQuestionsProvider({ 13 | required IRandomQuestionsLoader loader, 14 | required ICrashWrapper crashWrapper, 15 | }) : _loader = loader, 16 | _crashWrapper = crashWrapper; 17 | 18 | final IRandomQuestionsLoader _loader; 19 | final ICrashWrapper _crashWrapper; 20 | 21 | @override 22 | Future> get() => 23 | _crashWrapper.executeAndReport(() => _loader.get()); 24 | } 25 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/lib/www_questions.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_questions/src/di/di_module.dart'; 2 | export 'package:www_questions/src/presentation/route_page.dart'; 3 | export 'package:www_questions/src/redux/middleware.dart'; 4 | export 'package:www_questions/src/redux/reducer.dart'; 5 | export 'package:www_questions/src/redux/state.dart'; 6 | export 'package:www_questions/src/redux/state_holder.dart'; 7 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/test/mocks/mocks.dart: -------------------------------------------------------------------------------- 1 | import 'package:mocktail/mocktail.dart'; 2 | import 'package:www_analytics/www_analytics.dart'; 3 | import 'package:www_api/www_api.dart'; 4 | 5 | class MockRandomQuestionsLoader extends Mock implements IRandomQuestionsLoader { 6 | } 7 | 8 | class MockCrashWrapper extends Mock implements ICrashWrapper {} 9 | -------------------------------------------------------------------------------- /www-app/feature/www_questions/test/service/test_data_1.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_models/www_models.dart'; 2 | 3 | const expectedRandomQuestions1 = [ 4 | Question( 5 | id: '872756', 6 | info: QuestionInfo( 7 | id: '872756', 8 | tourInfo: TourInfo( 9 | id: '51740', 10 | tournamentInfo: TournamentInfo( 11 | id: '495', 12 | ), 13 | ), 14 | ), 15 | ), 16 | Question( 17 | id: '925260', 18 | info: QuestionInfo( 19 | id: '925260', 20 | tourInfo: TourInfo( 21 | id: '54534', 22 | tournamentInfo: TournamentInfo( 23 | id: '735', 24 | ), 25 | ), 26 | ), 27 | ), 28 | ]; 29 | -------------------------------------------------------------------------------- /www-app/feature/www_rating/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_rating/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_rating/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleRating extends WWWDIModule { 7 | const WWWDIModuleRating() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_rating/lib/src/service/rating.dart: -------------------------------------------------------------------------------- 1 | import 'package:app_review/app_review.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_analytics/www_analytics.dart'; 4 | 5 | abstract class IRatingService { 6 | Future rateApp(); 7 | } 8 | 9 | @LazySingleton(as: IRatingService) 10 | class RatingService implements IRatingService { 11 | const RatingService({ 12 | required ICrashWrapper crashWrapper, 13 | }) : _crashWrapper = crashWrapper; 14 | 15 | final ICrashWrapper _crashWrapper; 16 | 17 | @override 18 | Future rateApp() => 19 | _crashWrapper.executeAndReport(() => AppReview.storeListing); 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/www_rating/lib/www_rating.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_rating/src/di/di_module.dart'; 2 | export 'package:www_rating/src/redux/middleware.dart'; 3 | -------------------------------------------------------------------------------- /www-app/feature/www_rating/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_rating 2 | description: A rate-the-app feature 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | app_review: ^2.1.2+1 11 | flutter: 12 | sdk: flutter 13 | flutter_rating_bar: ^4.0.1 14 | flutter_svg: ^2.0.7 15 | injectable: 2.4.2 16 | www_analytics: 17 | path: ../../utils/www_analytics 18 | www_di: 19 | path: ../../utils/www_di 20 | www_dialogs: 21 | path: ../../utils/www_dialogs 22 | www_localization: 23 | path: ../../core/www_localization 24 | www_preferences: 25 | path: ../../utils/www_preferences 26 | www_redux: 27 | path: ../../utils/www_redux 28 | www_redux_actions: 29 | path: ../shared/www_redux_actions 30 | www_theme: 31 | path: ../../design/www_theme 32 | 33 | dev_dependencies: 34 | build_runner: 2.4.11 35 | injectable_generator: 2.6.1 36 | www_analysis: 37 | path: ../../utils/www_analysis 38 | 39 | -------------------------------------------------------------------------------- /www-app/feature/www_settings/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_settings/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_settings/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleSettings extends WWWDIModule { 7 | const WWWDIModuleSettings() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_settings/lib/src/redux/state.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_models/www_models.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | 6 | part 'state.freezed.dart'; 7 | 8 | @freezed 9 | class SettingsState with _$SettingsState implements IState { 10 | const factory SettingsState({ 11 | required AppTheme appTheme, 12 | required TextScale textScale, 13 | required bool notifyShortTimerExpiration, 14 | required bool notifyLongTimerExpiration, 15 | }) = _SettingsState; 16 | } 17 | -------------------------------------------------------------------------------- /www-app/feature/www_settings/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_settings/src/redux/state.dart'; 4 | 5 | abstract class ISettingsStateHolder implements IState { 6 | Option get settingsState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_settings/lib/www_settings.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_settings/src/di/di_module.dart'; 2 | export 'package:www_settings/src/presentation/route_page.dart'; 3 | export 'package:www_settings/src/redux/middleware.dart'; 4 | export 'package:www_settings/src/redux/reducer.dart'; 5 | export 'package:www_settings/src/redux/state.dart'; 6 | export 'package:www_settings/src/redux/state_holder.dart'; 7 | -------------------------------------------------------------------------------- /www-app/feature/www_settings/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_settings 2 | description: WWW app settings feature 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | injectable: 2.4.2 13 | www_analytics: 14 | path: ../../utils/www_analytics 15 | www_di: 16 | path: ../../utils/www_di 17 | www_localization: 18 | path: ../../core/www_localization 19 | www_preferences: 20 | path: ../../utils/www_preferences 21 | www_redux: 22 | path: ../../utils/www_redux 23 | www_redux_actions: 24 | path: ../shared/www_redux_actions 25 | www_theme: 26 | path: ../../design/www_theme 27 | www_widgets: 28 | path: ../../design/www_widgets 29 | 30 | dev_dependencies: 31 | build_runner: 2.4.11 32 | injectable_generator: 2.6.1 33 | www_analysis: 34 | path: ../../utils/www_analysis 35 | -------------------------------------------------------------------------------- /www-app/feature/www_sharing/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_sharing/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_sharing/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleSharing extends WWWDIModule { 7 | const WWWDIModuleSharing() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_sharing/lib/src/service/sharing.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:share/share.dart'; 3 | import 'package:www_analytics/www_analytics.dart'; 4 | 5 | abstract class ISharingService { 6 | Future share(String text); 7 | } 8 | 9 | @LazySingleton(as: ISharingService) 10 | class SharingService implements ISharingService { 11 | const SharingService({ 12 | required ICrashWrapper crashWrapper, 13 | }) : _crashWrapper = crashWrapper; 14 | 15 | final ICrashWrapper _crashWrapper; 16 | 17 | @override 18 | Future share(String text) => 19 | _crashWrapper.executeAndReport(() => Share.share(text)); 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/www_sharing/lib/www_sharing.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_sharing/src/di/di_module.dart'; 2 | export 'package:www_sharing/src/redux/middleware.dart'; 3 | -------------------------------------------------------------------------------- /www-app/feature/www_sharing/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_sharing 2 | description: Share content feature 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | injectable: 2.4.2 13 | share: ^2.0.4 14 | www_analytics: 15 | path: ../../utils/www_analytics 16 | www_constants: 17 | path: ../../core/www_constants 18 | www_di: 19 | path: ../../utils/www_di 20 | www_redux: 21 | path: ../../utils/www_redux 22 | www_redux_actions: 23 | path: ../shared/www_redux_actions 24 | 25 | dev_dependencies: 26 | build_runner: 2.4.11 27 | injectable_generator: 2.6.1 28 | www_analysis: 29 | path: ../../utils/www_analysis 30 | -------------------------------------------------------------------------------- /www-app/feature/www_timer/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_timer/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_timer/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleTimer extends WWWDIModule { 7 | const WWWDIModuleTimer() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_timer/lib/src/redux/state.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:www_models/www_models.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | 6 | part 'state.freezed.dart'; 7 | 8 | @freezed 9 | class TimerState with _$TimerState implements IState { 10 | const factory TimerState({ 11 | required TimerType timerType, 12 | required int secondsLeft, 13 | required bool isRunning, 14 | }) = _TimerState; 15 | 16 | factory TimerState.initial({TimerType timerType = TimerType.normal}) => 17 | TimerState( 18 | timerType: timerType, 19 | secondsLeft: Timers.getSeconds(timerType), 20 | isRunning: false, 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /www-app/feature/www_timer/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_timer/src/redux/state.dart'; 4 | 5 | abstract class ITimerStateHolder implements IState { 6 | Option get timerState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_timer/lib/src/service/sound.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:audioplayers/audioplayers.dart'; 4 | import 'package:injectable/injectable.dart'; 5 | import 'package:www_analytics/www_analytics.dart'; 6 | 7 | abstract class ISoundService { 8 | void init(); 9 | 10 | Future playSound(); 11 | } 12 | 13 | @LazySingleton(as: ISoundService) 14 | class SoundService implements ISoundService { 15 | SoundService({ 16 | required ICrashWrapper crashWrapper, 17 | }) : _crashWrapper = crashWrapper; 18 | 19 | final ICrashWrapper _crashWrapper; 20 | late final AudioPlayer _audioPlayer; 21 | 22 | static const _timerAssetName = 'timer.mp3'; 23 | 24 | @override 25 | void init() { 26 | _audioPlayer = AudioPlayer(); 27 | } 28 | 29 | @override 30 | Future playSound() => _crashWrapper 31 | .executeAndReport(() => _audioPlayer.play(AssetSource(_timerAssetName))); 32 | } 33 | -------------------------------------------------------------------------------- /www-app/feature/www_timer/lib/src/service/vibrating.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:vibration/vibration.dart'; 3 | import 'package:www_analytics/www_analytics.dart'; 4 | 5 | abstract class IVibratingService { 6 | Future vibrate(); 7 | } 8 | 9 | @LazySingleton(as: IVibratingService) 10 | class VibratingService implements IVibratingService { 11 | const VibratingService({ 12 | required ICrashWrapper crashWrapper, 13 | }) : _crashWrapper = crashWrapper; 14 | 15 | final ICrashWrapper _crashWrapper; 16 | 17 | @override 18 | Future vibrate() => _crashWrapper.executeAndReport(() async { 19 | if (await Vibration.hasVibrator() ?? false) { 20 | await Vibration.vibrate(); 21 | } 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /www-app/feature/www_timer/lib/www_timer.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_timer/src/di/di_module.dart'; 2 | export 'package:www_timer/src/redux/middleware.dart'; 3 | export 'package:www_timer/src/redux/reducer.dart'; 4 | export 'package:www_timer/src/redux/state.dart'; 5 | export 'package:www_timer/src/redux/state_holder.dart'; 6 | export 'package:www_timer/src/service/sound.dart'; 7 | -------------------------------------------------------------------------------- /www-app/feature/www_timer/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_timer 2 | description: Timer feature 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | audioplayers: ^5.0.0 11 | flutter: 12 | sdk: flutter 13 | freezed_annotation: 2.4.1 14 | injectable: 2.4.2 15 | path_provider: ^2.0.15 16 | vibration: ^1.8.1 17 | www_analytics: 18 | path: ../../utils/www_analytics 19 | www_di: 20 | path: ../../utils/www_di 21 | www_models: 22 | path: ../../domain/www_models 23 | www_redux: 24 | path: ../../utils/www_redux 25 | www_redux_actions: 26 | path: ../shared/www_redux_actions 27 | www_settings: 28 | path: ../www_settings 29 | www_theme: 30 | path: ../../design/www_theme 31 | www_utils: 32 | path: ../../utils/www_utils 33 | www_widgets: 34 | path: ../../design/www_widgets 35 | 36 | dev_dependencies: 37 | build_runner: 2.4.11 38 | injectable_generator: 2.6.1 39 | www_analysis: 40 | path: ../../utils/www_analysis 41 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_tournament_details/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleTournamentDetails extends WWWDIModule { 7 | const WWWDIModuleTournamentDetails() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/lib/src/presentation/app_bar_buttons/more.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_tournament_details/src/presentation/bottom_sheet/bottom_sheet.dart'; 3 | 4 | class TournamentDetailsAppBarMoreButton extends StatelessWidget { 5 | const TournamentDetailsAppBarMoreButton({Key? key}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) => IconButton( 9 | icon: const Icon(Icons.more_vert), 10 | onPressed: () => _showMenu(context), 11 | ); 12 | 13 | void _showMenu(BuildContext context) => showModalBottomSheet( 14 | context: context, 15 | builder: (context) => const TournamentDetailsBottomSheet(), 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/lib/src/presentation/error_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_models/www_models.dart'; 3 | import 'package:www_redux/www_redux.dart'; 4 | import 'package:www_redux_actions/www_redux_actions.dart'; 5 | import 'package:www_widgets/www_widgets.dart'; 6 | 7 | class TournamentDetailsErrorPage extends StatelessWidget { 8 | const TournamentDetailsErrorPage({ 9 | Key? key, 10 | required this.info, 11 | this.exception, 12 | }) : super(key: key); 13 | 14 | final Exception? exception; 15 | final TournamentInfo info; 16 | 17 | @override 18 | Widget build(BuildContext context) => SliverFillRemaining( 19 | hasScrollBody: false, 20 | child: ErrorMessage( 21 | exception: exception, 22 | retryFunction: () => _loadTournament(context), 23 | color: Theme.of(context).primaryTextTheme.bodyMedium!.color, 24 | ), 25 | ); 26 | 27 | void _loadTournament(BuildContext context) => 28 | context.dispatch(UserActionTournament.load(info: info)); 29 | } 30 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/lib/src/presentation/route_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_theme/www_theme.dart'; 3 | import 'package:www_tournament_details/src/presentation/app_bar.dart'; 4 | import 'package:www_tournament_details/src/presentation/page_content.dart'; 5 | 6 | @immutable 7 | class TournamentDetailsRoutePage extends StatelessWidget { 8 | const TournamentDetailsRoutePage({Key? key}) : super(key: key); 9 | 10 | static const String routeName = 'tournament'; 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | final styleConfiguration = 15 | context.styleConfig.tournamentDetailsStyleConfiguration; 16 | 17 | return Scaffold( 18 | backgroundColor: styleConfiguration.scaffoldBackground, 19 | body: const CustomScrollView( 20 | physics: BouncingScrollPhysics(), 21 | slivers: [ 22 | TournamentDetailsAppBar(), 23 | TournamentDetailsPageContent(), 24 | ], 25 | ), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_tournament_details/src/redux/state.dart'; 4 | 5 | abstract class ITournamentDetailsStateHolder implements IState { 6 | Option get tournamentState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/lib/src/utils/measure_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | Size measureText( 4 | BuildContext context, String text, TextStyle style, double width) => 5 | (TextPainter( 6 | text: TextSpan(text: text, style: style), 7 | textScaleFactor: MediaQuery.of(context).textScaleFactor, 8 | textDirection: Directionality.of(context)) 9 | ..layout(minWidth: 0, maxWidth: width)) 10 | .size; 11 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/lib/www_tournament_details.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_tournament_details/src/di/di_module.dart'; 2 | export 'package:www_tournament_details/src/presentation/route_page.dart'; 3 | export 'package:www_tournament_details/src/redux/middleware.dart'; 4 | export 'package:www_tournament_details/src/redux/reducer.dart'; 5 | export 'package:www_tournament_details/src/redux/state.dart'; 6 | export 'package:www_tournament_details/src/redux/state_holder.dart'; 7 | export 'package:www_tournament_details/src/service/tournament_details_provider.dart'; 8 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/test/mocks/mocks.dart: -------------------------------------------------------------------------------- 1 | import 'package:mocktail/mocktail.dart'; 2 | import 'package:www_analytics/www_analytics.dart'; 3 | import 'package:www_api/www_api.dart'; 4 | import 'package:www_cache/www_cache.dart'; 5 | import 'package:www_tournament_status/www_tournament_status.dart'; 6 | 7 | class MockTournamentDetailsLoader extends Mock 8 | implements ITournamentDetailsLoader {} 9 | 10 | class MockTournamentsCache extends Mock implements ITournamentsCache {} 11 | 12 | class MockToursCache extends Mock implements IToursCache {} 13 | 14 | class MockTournamentStatusService extends Mock 15 | implements ITournamentStatusService {} 16 | 17 | class MockCrashWrapper extends Mock implements ICrashWrapper {} 18 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/test/service/test_data_1.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_models/www_models.dart'; 2 | 3 | const tournamentInfo1 = TournamentInfo( 4 | id: '70684', 5 | id2: 'thanos19.5_u', 6 | ); 7 | 8 | const expectedTournamentDetails1 = Tournament( 9 | id: '70684', 10 | id2: 'thanos19.5_u', 11 | info: tournamentInfo1, 12 | tours: [ 13 | Tour( 14 | id: '70685', 15 | info: TourInfo( 16 | id: '70685', 17 | tournamentInfo: tournamentInfo1, 18 | ), 19 | ), 20 | Tour( 21 | id: '70686', 22 | info: TourInfo( 23 | id: '70686', 24 | tournamentInfo: tournamentInfo1, 25 | ), 26 | ), 27 | ], 28 | ); 29 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_details/test/service/test_data_2.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_models/www_models.dart'; 2 | 3 | const tournamentInfo2 = TournamentInfo( 4 | id: '7', 5 | id2: 't', 6 | ); 7 | 8 | const expectedTournamentDetails2 = Tournament( 9 | id: '7', 10 | id2: 't', 11 | info: tournamentInfo2, 12 | tours: [ 13 | Tour( 14 | id: '7', 15 | info: TourInfo( 16 | id: '7', 17 | tournamentInfo: tournamentInfo2, 18 | ), 19 | ), 20 | ], 21 | ); 22 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_tours/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_tournament_tours/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_tournament_tours/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleTournamentTours extends WWWDIModule { 7 | const WWWDIModuleTournamentTours() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_tours/lib/src/presentation/question_data_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_models/www_models.dart'; 3 | import 'package:www_theme/www_theme.dart'; 4 | import 'package:www_tournament_tours/src/presentation/question_template_tile.dart'; 5 | 6 | class TourDetailsQuestionDataTile extends StatelessWidget { 7 | const TourDetailsQuestionDataTile({ 8 | Key? key, 9 | required this.question, 10 | this.onTap, 11 | }) : super(key: key); 12 | 13 | final Question question; 14 | final GestureTapCallback? onTap; 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | final styleConfiguration = 19 | context.styleConfig.tournamentDetailsStyleConfiguration; 20 | 21 | return TourDetailsQuestionTemplateTile( 22 | onTap: onTap, 23 | heroTag: '${question.info.id}', 24 | child: Text( 25 | '${question.info.number}. ${question.display}', 26 | style: styleConfiguration.questionTextStyle, 27 | ), 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_tours/lib/src/presentation/question_loading_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_theme/www_theme.dart'; 3 | import 'package:www_tournament_tours/src/presentation/question_template_tile.dart'; 4 | import 'package:www_widgets/www_widgets.dart'; 5 | 6 | class TourDetailsQuestionLoadingTile extends StatelessWidget { 7 | const TourDetailsQuestionLoadingTile({Key? key}) : super(key: key); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | final styleConfiguration = 12 | context.styleConfig.tournamentDetailsStyleConfiguration; 13 | 14 | return TourDetailsQuestionTemplateTile( 15 | child: TextStub( 16 | textStyle: styleConfiguration.questionTextStyle, 17 | ), 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_tours/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_tournament_tours/src/redux/state.dart'; 4 | 5 | abstract class ITournamentToursStateHolder implements IState { 6 | Option get toursState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_tours/lib/www_tournament_tours.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_tournament_tours/src/di/di_module.dart'; 2 | export 'package:www_tournament_tours/src/presentation/route_tile.dart'; 3 | export 'package:www_tournament_tours/src/presentation/stub_tile.dart'; 4 | export 'package:www_tournament_tours/src/redux/middleware.dart'; 5 | export 'package:www_tournament_tours/src/redux/reducer.dart'; 6 | export 'package:www_tournament_tours/src/redux/state.dart'; 7 | export 'package:www_tournament_tours/src/redux/state_holder.dart'; 8 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_tours/test/mocks/mocks.dart: -------------------------------------------------------------------------------- 1 | import 'package:mocktail/mocktail.dart'; 2 | import 'package:www_analytics/www_analytics.dart'; 3 | import 'package:www_api/www_api.dart'; 4 | import 'package:www_cache/www_cache.dart'; 5 | 6 | class MockTourDetailsLoader extends Mock implements ITourDetailsLoader {} 7 | 8 | class MockTournamentsCache extends Mock implements ITournamentsCache {} 9 | 10 | class MockToursCache extends Mock implements IToursCache {} 11 | 12 | class MockCrashWrapper extends Mock implements ICrashWrapper {} 13 | -------------------------------------------------------------------------------- /www-app/feature/www_tournament_tours/test/service/tour_details_provider/test_data_1.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_models/www_models.dart'; 2 | 3 | const expectedTourDetails1 = Tour( 4 | id: '1.1', 5 | info: TourInfo( 6 | id: '1.1', 7 | tournamentInfo: TournamentInfo( 8 | id: '1', 9 | ), 10 | ), 11 | ); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_tournaments_search/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleTournamentsSearch extends WWWDIModule { 7 | const WWWDIModuleTournamentsSearch() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/lib/src/presentation/empty_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_localization/www_localization.dart'; 3 | import 'package:www_theme/www_theme.dart'; 4 | 5 | class SearchEmptyPage extends StatelessWidget { 6 | const SearchEmptyPage({Key? key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) => SliverFillRemaining( 10 | hasScrollBody: false, 11 | child: Center( 12 | child: Text( 13 | context.translations.emptySearchResults, 14 | textAlign: TextAlign.center, 15 | style: 16 | context.styleConfig.searchStyleConfiguration.noResultsTextStyle, 17 | ), 18 | ), 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/lib/src/presentation/error_message.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_redux_actions/www_redux_actions.dart'; 4 | import 'package:www_theme/www_theme.dart'; 5 | import 'package:www_widgets/www_widgets.dart'; 6 | 7 | class SearchErrorMessage extends StatelessWidget { 8 | const SearchErrorMessage({ 9 | Key? key, 10 | this.dense = false, 11 | this.exception, 12 | }) : super(key: key); 13 | 14 | final bool dense; 15 | final Exception? exception; 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | final styleConfiguration = context.styleConfig.searchStyleConfiguration; 20 | 21 | return ErrorMessage( 22 | exception: exception, 23 | retryFunction: () => _reload(context), 24 | color: styleConfiguration.errorColor, 25 | dense: dense, 26 | ); 27 | } 28 | 29 | void _reload(BuildContext context) => 30 | context.dispatch(const UserActionSearch.execute()); 31 | } 32 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/lib/src/presentation/error_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_tournaments_search/src/presentation/error_message.dart'; 3 | 4 | class SearchErrorPage extends StatelessWidget { 5 | const SearchErrorPage({ 6 | Key? key, 7 | this.exception, 8 | }) : super(key: key); 9 | 10 | final Exception? exception; 11 | 12 | @override 13 | Widget build(BuildContext context) => SliverFillRemaining( 14 | hasScrollBody: false, 15 | child: SearchErrorMessage( 16 | exception: exception, 17 | dense: false, 18 | ), 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/lib/src/presentation/loading_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_theme/www_theme.dart'; 3 | 4 | import 'package:www_widgets/www_widgets.dart'; 5 | 6 | class SearchLoadingPage extends StatelessWidget { 7 | const SearchLoadingPage({Key? key}) : super(key: key); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | final styleConfiguration = context.styleConfig.searchStyleConfiguration; 12 | 13 | return TournamentsGrid( 14 | stubTournamentsCount: styleConfiguration.stubTournamentsCount, 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_tournaments_search/src/redux/state.dart'; 4 | 5 | abstract class ISearchStateHolder implements IState { 6 | Option get searchState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/lib/www_tournaments_search.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_tournaments_search/src/di/di_module.dart'; 2 | export 'package:www_tournaments_search/src/presentation/route_page.dart'; 3 | export 'package:www_tournaments_search/src/redux/middleware.dart'; 4 | export 'package:www_tournaments_search/src/redux/reducer.dart'; 5 | export 'package:www_tournaments_search/src/redux/state.dart'; 6 | export 'package:www_tournaments_search/src/redux/state_holder.dart'; 7 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/test/mocks/mocks.dart: -------------------------------------------------------------------------------- 1 | import 'package:mocktail/mocktail.dart'; 2 | import 'package:www_analytics/www_analytics.dart'; 3 | import 'package:www_api/www_api.dart'; 4 | import 'package:www_tournament_status/www_tournament_status.dart'; 5 | 6 | class MockSearchLoader extends Mock implements ISearchLoader {} 7 | 8 | class MockTournamentStatusService extends Mock 9 | implements ITournamentStatusService {} 10 | 11 | class MockCrashWrapper extends Mock implements ICrashWrapper {} 12 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_search/test/service/search_provider/test_data_1.dart: -------------------------------------------------------------------------------- 1 | import 'package:www_models/www_models.dart'; 2 | 3 | const expectedSearchTournaments1 = [ 4 | Tournament( 5 | id2: '1', 6 | info: TournamentInfo( 7 | id2: '1', 8 | ), 9 | ), 10 | Tournament( 11 | id2: '2', 12 | info: TournamentInfo( 13 | id2: '2', 14 | ), 15 | ), 16 | ]; 17 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_tree/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_tree/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_tournaments_tree/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModuleTournamentsTree extends WWWDIModule { 7 | const WWWDIModuleTournamentsTree() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_tree/lib/src/presentation/loading_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:www_theme/www_theme.dart'; 3 | import 'package:www_widgets/www_widgets.dart'; 4 | 5 | class TournamentsTreeLoadingPage extends StatelessWidget { 6 | const TournamentsTreeLoadingPage({Key? key}) : super(key: key); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | final styleConfiguration = 11 | context.styleConfig.tournamentsTreeStyleConfiguration; 12 | 13 | return TournamentsGrid( 14 | stubTournamentsCount: styleConfiguration.stubTournamentsCount, 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_tree/lib/src/redux/state_holder.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_redux/www_redux.dart'; 3 | import 'package:www_tournaments_tree/src/redux/state.dart'; 4 | 5 | abstract class ITournamentsTreeStateHolder implements IState { 6 | Option get tournamentsTreeState; 7 | } 8 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_tree/lib/www_tournaments_tree.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_tournaments_tree/src/di/di_module.dart'; 2 | export 'package:www_tournaments_tree/src/presentation/route_page.dart'; 3 | export 'package:www_tournaments_tree/src/redux/middleware.dart'; 4 | export 'package:www_tournaments_tree/src/redux/reducer.dart'; 5 | export 'package:www_tournaments_tree/src/redux/state.dart'; 6 | export 'package:www_tournaments_tree/src/redux/state_holder.dart'; 7 | -------------------------------------------------------------------------------- /www-app/feature/www_tournaments_tree/test/mocks/mocks.dart: -------------------------------------------------------------------------------- 1 | import 'package:mocktail/mocktail.dart'; 2 | import 'package:www_analytics/www_analytics.dart'; 3 | import 'package:www_api/www_api.dart'; 4 | import 'package:www_cache/www_cache.dart'; 5 | import 'package:www_tournament_status/www_tournament_status.dart'; 6 | 7 | class MockTournamentsTreeLoader extends Mock implements ITournamentsTreeLoader { 8 | } 9 | 10 | class MockTournamentStatusService extends Mock 11 | implements ITournamentStatusService {} 12 | 13 | class MockTournamentsTreeCache extends Mock implements ITournamentsTreeCache {} 14 | 15 | class MockCrashWrapper extends Mock implements ICrashWrapper {} 16 | -------------------------------------------------------------------------------- /www-app/melos.yaml: -------------------------------------------------------------------------------- 1 | name: www 2 | 3 | packages: 4 | - ./** 5 | 6 | scripts: 7 | generate: 8 | run: melos exec -c 1 --depends-on="build_runner" --flutter -- "dart run build_runner build --delete-conflicting-outputs" 9 | 10 | get: 11 | run: melos exec -- "flutter pub get" 12 | 13 | test: 14 | run: melos exec --dir-exists="test" -- "flutter test" 15 | -------------------------------------------------------------------------------- /www-app/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www 2 | 3 | environment: 4 | sdk: ^3.0.6 5 | 6 | dev_dependencies: 7 | melos: ^3.1.1 8 | -------------------------------------------------------------------------------- /www-app/utils/www_analysis/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_analysis 2 | description: A set of code analysis rules for www_* packages 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | extra_pedantic: ^4.0.0 11 | flutter: 12 | sdk: flutter 13 | -------------------------------------------------------------------------------- /www-app/utils/www_analytics/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/utils/www_analytics/lib/src/config/firebase_config_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_analytics/src/config/firebase_config_parameters.dart'; 4 | 5 | @module 6 | abstract class FirebaseConfigInjectableModule { 7 | @Named(FirebaseConfigParameters.enableAnalytics) 8 | bool get enableAnalytics => !kDebugMode; 9 | 10 | @Named(FirebaseConfigParameters.enableCrashlytics) 11 | bool get enableCrashlytics => !kDebugMode; 12 | } 13 | -------------------------------------------------------------------------------- /www-app/utils/www_analytics/lib/src/config/firebase_config_parameters.dart: -------------------------------------------------------------------------------- 1 | abstract class FirebaseConfigParameters { 2 | static const enableAnalytics = 'enableAnalytics'; 3 | static const enableCrashlytics = 'enableCrashlytics'; 4 | } 5 | -------------------------------------------------------------------------------- /www-app/utils/www_analytics/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_analytics/src/di/di_module.config.dart'; 4 | import 'package:www_di/www_di.dart'; 5 | 6 | class WWWDIModuleAnalytics extends WWWDIModule { 7 | const WWWDIModuleAnalytics() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/utils/www_analytics/lib/src/service/crash_wrapper.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:www_analytics/src/service/crashes.dart'; 3 | 4 | abstract class ICrashWrapper { 5 | Future executeAndReport(Future Function() action); 6 | } 7 | 8 | @LazySingleton(as: ICrashWrapper) 9 | class CrashWrapper implements ICrashWrapper { 10 | const CrashWrapper({ 11 | required ICrashService crashService, 12 | }) : _crashService = crashService; 13 | 14 | final ICrashService _crashService; 15 | 16 | @override 17 | Future executeAndReport(Future Function() action) async { 18 | try { 19 | final result = await action(); 20 | return result; 21 | } on Exception catch (e, s) { 22 | await _crashService.logException(e, stackTrace: s); 23 | rethrow; 24 | } on Error catch (e, s) { 25 | await _crashService.logError(e, stackTrace: s); 26 | rethrow; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /www-app/utils/www_analytics/lib/www_analytics.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_analytics/src/di/di_module.dart'; 2 | export 'package:www_analytics/src/service/analytics.dart'; 3 | export 'package:www_analytics/src/service/crash_wrapper.dart'; 4 | export 'package:www_analytics/src/service/crashes.dart'; 5 | export 'package:www_analytics/src/service/firebase.dart'; 6 | -------------------------------------------------------------------------------- /www-app/utils/www_analytics/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_analytics 2 | description: Analytics and Crashlytics for www_* packages 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | firebase_analytics: ^10.4.4 11 | firebase_core: ^2.15.0 12 | firebase_crashlytics: ^3.3.4 13 | flutter: 14 | sdk: flutter 15 | injectable: 2.4.2 16 | www_di: 17 | path: ../www_di 18 | www_logger: 19 | path: ../www_logger/ 20 | 21 | dev_dependencies: 22 | build_runner: 2.4.11 23 | injectable_generator: 2.6.1 24 | www_analysis: 25 | path: ../www_analysis 26 | -------------------------------------------------------------------------------- /www-app/utils/www_background_runner/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/utils/www_background_runner/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_background_runner/src/di/di_module.config.dart'; 4 | import 'package:www_di/www_di.dart'; 5 | 6 | class WWWDIModuleBackgroundRunner extends WWWDIModule { 7 | const WWWDIModuleBackgroundRunner() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/utils/www_background_runner/lib/www_background_runner.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_background_runner/src/di/di_module.dart'; 2 | export 'package:www_background_runner/src/service/background_runner.dart'; 3 | -------------------------------------------------------------------------------- /www-app/utils/www_background_runner/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_background_runner 2 | description: Background runner 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | dartz: ^0.10.1 11 | flutter: 12 | sdk: flutter 13 | injectable: 2.4.2 14 | isolate: ^2.1.1 #discontinued 15 | www_di: 16 | path: ../www_di 17 | 18 | dev_dependencies: 19 | build_runner: 2.4.11 20 | injectable_generator: 2.6.1 21 | www_analysis: 22 | path: ../www_analysis 23 | -------------------------------------------------------------------------------- /www-app/utils/www_di/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/utils/www_di/lib/src/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | 3 | typedef GetItInitializer = void Function(GetIt getIt); 4 | 5 | abstract class WWWDIModule { 6 | const WWWDIModule(this._initializer); 7 | 8 | final GetItInitializer _initializer; 9 | 10 | void init(GetIt getIt) => _initializer(getIt); 11 | } 12 | -------------------------------------------------------------------------------- /www-app/utils/www_di/lib/www_di.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_di/src/di_module.dart'; 2 | -------------------------------------------------------------------------------- /www-app/utils/www_di/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_di 2 | description: Dependency inversion mechanism for www_* packages 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | get_it: 7.7.0 13 | injectable: 2.4.2 14 | www_logger: 15 | path: ../www_logger/ 16 | 17 | dev_dependencies: 18 | build_runner: 2.4.11 19 | injectable_generator: 2.6.1 20 | www_analysis: 21 | path: ../www_analysis 22 | -------------------------------------------------------------------------------- /www-app/utils/www_dialogs/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/utils/www_dialogs/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_dialogs/src/di/di_module.config.dart'; 5 | import 'package:www_dialogs/src/service/dialogs.dart'; 6 | 7 | class WWWDIModuleDialogs extends WWWDIModule { 8 | const WWWDIModuleDialogs() : super(_initImpl); 9 | 10 | static void _initImpl(GetIt getIt) { 11 | _init(getIt); 12 | 13 | getIt.registerLazySingleton( 14 | () => getIt() as IDialogHelper); 15 | } 16 | } 17 | 18 | @injectableInit 19 | void _init(GetIt getIt) => getIt.init(); 20 | -------------------------------------------------------------------------------- /www-app/utils/www_dialogs/lib/www_dialogs.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_dialogs/src/di/di_module.dart'; 2 | export 'package:www_dialogs/src/presentation/dialog_presenter.dart'; 3 | export 'package:www_dialogs/src/service/dialogs.dart'; 4 | -------------------------------------------------------------------------------- /www-app/utils/www_dialogs/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_dialogs 2 | description: Dialogs mechanism 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | injectable: 2.4.2 13 | www_analytics: 14 | path: ../www_analytics 15 | 16 | dev_dependencies: 17 | build_runner: 2.4.11 18 | injectable_generator: 2.6.1 19 | www_analysis: 20 | path: ../www_analysis 21 | -------------------------------------------------------------------------------- /www-app/utils/www_logger/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/utils/www_logger/lib/src/logger.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'package:flutter/foundation.dart'; 3 | 4 | const _maxLogSize = 512; 5 | 6 | void log(dynamic object) { 7 | if (object != null && !kReleaseMode) { 8 | final data = _split(object.toString(), _maxLogSize); 9 | data.forEach(debugPrint); 10 | } 11 | } 12 | 13 | Iterable _split(String string, int size) sync* { 14 | for (var i = 0; i < string.length; i += size) { 15 | yield string.substring(i, min(i + size, string.length)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /www-app/utils/www_logger/lib/www_logger.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_logger/src/logger.dart'; 2 | -------------------------------------------------------------------------------- /www-app/utils/www_logger/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_logger 2 | description: Logging utility 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | dev_dependencies: 14 | www_analysis: 15 | path: ../www_analysis 16 | -------------------------------------------------------------------------------- /www-app/utils/www_preferences/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/utils/www_preferences/lib/src/di/di_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:www_di/www_di.dart'; 4 | import 'package:www_preferences/src/di/di_module.config.dart'; 5 | 6 | class WWWDIModulePreferences extends WWWDIModule { 7 | const WWWDIModulePreferences() : super(_init); 8 | } 9 | 10 | @injectableInit 11 | void _init(GetIt getIt) => getIt.init(); 12 | -------------------------------------------------------------------------------- /www-app/utils/www_preferences/lib/www_preferences.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_preferences/src/di/di_module.dart'; 2 | export 'package:www_preferences/src/service/preferences.dart'; 3 | -------------------------------------------------------------------------------- /www-app/utils/www_preferences/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_preferences 2 | description: App preferences storage 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | injectable: 2.4.2 13 | shared_preferences: ^2.2.0 14 | www_analytics: 15 | path: ../www_analytics 16 | www_di: 17 | path: ../www_di 18 | 19 | dev_dependencies: 20 | build_runner: 2.4.11 21 | injectable_generator: 2.6.1 22 | www_analysis: 23 | path: ../www_analysis 24 | -------------------------------------------------------------------------------- /www-app/utils/www_redux/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/utils/www_redux/lib/src/extensions/context_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:flutter_redux/flutter_redux.dart'; 3 | import 'package:redux/redux.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | 6 | extension BuildContextX on BuildContext { 7 | void dispatch(IUserAction action) => 8 | StoreProvider.of(this).dispatch(action); 9 | 10 | Store store() => StoreProvider.of(this) as Store; 11 | } 12 | -------------------------------------------------------------------------------- /www-app/utils/www_redux/lib/src/presentation/store_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_redux/flutter_redux.dart'; 3 | import 'package:redux/redux.dart'; 4 | import 'package:www_redux/www_redux.dart'; 5 | 6 | class WWWStoreProvider extends StatelessWidget { 7 | const WWWStoreProvider({ 8 | Key? key, 9 | required this.store, 10 | required this.child, 11 | }) : super(key: key); 12 | 13 | final Store store; 14 | final Widget child; 15 | 16 | @override 17 | Widget build(BuildContext context) => StoreProvider( 18 | store: store, 19 | child: child, 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /www-app/utils/www_redux/lib/src/redux/action.dart: -------------------------------------------------------------------------------- 1 | /// A Redux action. 2 | abstract class IAction {} 3 | 4 | /// A Redux action meant to be triggered by the user. 5 | abstract class IUserAction implements IAction {} 6 | 7 | /// A Redux action meant to be triggered by the system only. 8 | abstract class ISystemAction implements IAction {} 9 | -------------------------------------------------------------------------------- /www-app/utils/www_redux/lib/src/redux/middleware.dart: -------------------------------------------------------------------------------- 1 | import 'package:redux/redux.dart'; 2 | import 'package:www_redux/src/redux/state.dart'; 3 | 4 | abstract class IMiddleware { 5 | Iterable> get middleware; 6 | } 7 | -------------------------------------------------------------------------------- /www-app/utils/www_redux/lib/src/redux/reducer.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:www_redux/src/redux/action.dart'; 3 | import 'package:www_redux/src/redux/state.dart'; 4 | 5 | abstract class IReducer { 6 | Option call(Option state, A action); 7 | } 8 | -------------------------------------------------------------------------------- /www-app/utils/www_redux/lib/src/redux/state.dart: -------------------------------------------------------------------------------- 1 | abstract class IState {} 2 | -------------------------------------------------------------------------------- /www-app/utils/www_redux/lib/www_redux.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_redux/src/extensions/context_extensions.dart'; 2 | export 'package:www_redux/src/presentation/store_connector.dart'; 3 | export 'package:www_redux/src/presentation/store_provider.dart'; 4 | export 'package:www_redux/src/redux/action.dart'; 5 | export 'package:www_redux/src/redux/middleware.dart'; 6 | export 'package:www_redux/src/redux/reducer.dart'; 7 | export 'package:www_redux/src/redux/state.dart'; 8 | -------------------------------------------------------------------------------- /www-app/utils/www_redux/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_redux 2 | description: Base Redux abstractions 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | dartz: ^0.10.1 11 | flutter: 12 | sdk: flutter 13 | flutter_redux: ^0.10.0 14 | 15 | dev_dependencies: 16 | www_analysis: 17 | path: ../www_analysis 18 | -------------------------------------------------------------------------------- /www-app/utils/www_test_utils/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/utils/www_test_utils/lib/src/test_arrange.dart: -------------------------------------------------------------------------------- 1 | import 'package:mocktail/mocktail.dart' as mocktail; 2 | 3 | abstract class TestArrange { 4 | static mocktail.When Function(T Function() x) get when => mocktail.when; 5 | 6 | static void registerFallbackValue(T value) => 7 | mocktail.registerFallbackValue(value); 8 | } 9 | -------------------------------------------------------------------------------- /www-app/utils/www_test_utils/lib/src/test_assert.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart' as flutter_test; 2 | import 'package:mocktail/mocktail.dart' as mocktail; 3 | 4 | abstract class TestAssert { 5 | static mocktail.VerificationResult Function(T Function() x) get verify => 6 | mocktail.verify; 7 | 8 | static mocktail.VerificationResult Function(T Function() x) 9 | get verifyNever => mocktail.verifyNever; 10 | 11 | static Future Function(T Function() x) get untilCalled => 12 | mocktail.untilCalled; 13 | 14 | static void expect(T actual, T matcher) => 15 | flutter_test.expect(actual, matcher); 16 | } 17 | -------------------------------------------------------------------------------- /www-app/utils/www_test_utils/lib/www_test_utils.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_test_utils/src/test_arrange.dart'; 2 | export 'package:www_test_utils/src/test_assert.dart'; 3 | -------------------------------------------------------------------------------- /www-app/utils/www_test_utils/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_test_utils 2 | description: Misc utils for testing 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | flutter_test: 13 | sdk: flutter 14 | mocktail: ^1.0.0 15 | www_analytics: 16 | path: ../www_analytics 17 | 18 | dev_dependencies: 19 | www_analysis: 20 | path: ../www_analysis 21 | -------------------------------------------------------------------------------- /www-app/utils/www_utils/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:www_analysis/analysis_options.yaml -------------------------------------------------------------------------------- /www-app/utils/www_utils/lib/src/duration_formatter.dart: -------------------------------------------------------------------------------- 1 | class DurationFormatter { 2 | DurationFormatter._(); 3 | 4 | static String formatSeconds(int seconds) => 5 | '${_twoDigits(seconds ~/ Duration.secondsPerMinute)}' 6 | ':' 7 | '${_twoDigits(seconds % 60)}'; 8 | 9 | static String _twoDigits(int n) => n >= 10 ? '$n' : '0$n'; 10 | } 11 | -------------------------------------------------------------------------------- /www-app/utils/www_utils/lib/src/network_exception.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | 3 | @immutable 4 | class NetworkException implements Exception { 5 | const NetworkException({this.message}); 6 | 7 | final String? message; 8 | 9 | @override 10 | String toString() => '$NetworkException ${message ?? ""}'; 11 | } 12 | -------------------------------------------------------------------------------- /www-app/utils/www_utils/lib/src/silent_operation.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | abstract class SilentOperation { 4 | static Future executeFunctionSilently(Future Function() action, 5 | {required T defaultValue}) async { 6 | try { 7 | return await action(); 8 | } on Exception { 9 | return defaultValue; 10 | } on Error { 11 | return defaultValue; 12 | } 13 | } 14 | 15 | static Future executeActionSilently( 16 | Future Function() action) async { 17 | try { 18 | return await action(); 19 | } on Exception { 20 | return; 21 | } on Error { 22 | return; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /www-app/utils/www_utils/lib/www_utils.dart: -------------------------------------------------------------------------------- 1 | export 'package:www_utils/src/duration_formatter.dart'; 2 | export 'package:www_utils/src/extensions/iterable_extensions.dart'; 3 | export 'package:www_utils/src/extensions/string_extensions.dart'; 4 | export 'package:www_utils/src/network_exception.dart'; 5 | export 'package:www_utils/src/silent_operation.dart'; 6 | export 'package:www_utils/src/uri_detector.dart'; 7 | -------------------------------------------------------------------------------- /www-app/utils/www_utils/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: www_utils 2 | description: Misc utils 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.4.1 7 | flutter: ^3.22.1 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | html_unescape: ^2.0.0 13 | 14 | dev_dependencies: 15 | www_analysis: 16 | path: ../www_analysis 17 | --------------------------------------------------------------------------------