diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart index 3683609e1..e644fcc61 100644 --- a/lib/app/view/app.dart +++ b/lib/app/view/app.dart @@ -2,6 +2,7 @@ import 'package:crossword_repository/crossword_repository.dart'; import 'package:flutter/material.dart'; import 'package:io_crossword/crossword/crossword.dart'; import 'package:io_crossword/l10n/l10n.dart'; +import 'package:io_crossword_ui/io_crossword_ui.dart'; import 'package:provider/provider.dart'; class App extends StatelessWidget { @@ -26,12 +27,7 @@ class AppView extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - theme: ThemeData( - appBarTheme: AppBarTheme( - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - ), - useMaterial3: true, - ), + theme: IoCrosswordTheme.themeData, localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, home: const CrosswordPage(), diff --git a/lib/game_intro/view/welcome_view.dart b/lib/game_intro/view/welcome_view.dart index 0145c7f2e..ecaceff90 100644 --- a/lib/game_intro/view/welcome_view.dart +++ b/lib/game_intro/view/welcome_view.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:intl/intl.dart'; import 'package:io_crossword/game_intro/game_intro.dart'; +import 'package:io_crossword/l10n/l10n.dart'; +import 'package:io_crossword_ui/io_crossword_ui.dart'; class WelcomeView extends StatelessWidget { const WelcomeView({super.key}); @@ -11,17 +14,62 @@ class WelcomeView extends StatelessWidget { @override Widget build(BuildContext context) { + final l10n = context.l10n; + final textTheme = Theme.of(context).textTheme; + return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text('Welcome!'), - const SizedBox(height: 32), - ElevatedButton( + const Placeholder(fallbackHeight: 150), + const SizedBox(height: IoCrosswordSpacing.xlg), + Text( + l10n.welcome, + style: textTheme.headlineLarge, + ), + const SizedBox(height: IoCrosswordSpacing.sm), + Text( + l10n.welcomeSubtitle, + style: textTheme.bodyMedium, + textAlign: TextAlign.center, + ), + const Spacer(), + const RecordProgress(), + const SizedBox(height: IoCrosswordSpacing.xxlg), + PrimaryButton( onPressed: () { context.read().add(const WelcomeCompleted()); }, - child: const Text('Continue'), + label: l10n.getStarted, + ), + ], + ); + } +} + +class RecordProgress extends StatelessWidget { + const RecordProgress({super.key}); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + + // TODO(any): Replace with real data + const solvedWords = 50234; + const totalWords = 100123; + + final f = NumberFormat.decimalPattern(l10n.localeName); + + return Column( + children: [ + Text(l10n.wordsToBreakRecord), + const SizedBox(height: IoCrosswordSpacing.sm), + LinearProgressIndicator( + value: 0.5, + minHeight: 4, + borderRadius: BorderRadius.circular(4), ), + const SizedBox(height: IoCrosswordSpacing.sm), + Text('${f.format(solvedWords)} / ${f.format(totalWords)}'), ], ); } diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 66ec0b833..b1e990515 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -1,25 +1,19 @@ { "@@locale": "en", - "counterAppBarTitle": "Counter", - "@counterAppBarTitle": { - "description": "Text shown in the AppBar of the Counter Page" + "welcome": "Welcome!", + "@welcome": { + "description": "Welcome label" }, - "loading": "Loading {label}...", - "@loading": { - "description": "Text for the loading page", - "placeholders": { - "label": { - "type": "String", - "example": "Stuff", - "description": "Label for what is being loaded" - } - } + "welcomeSubtitle": "Help solve the World's Largest Crossword, built with Gemini for Google I/O 2024", + "@welcomeSubtitle": { + "description": "Subtitle to be displayed in the welcome modal" }, - "loadingPhaseLabel": "{loadingPhase, select, audio{Delightful music} images{Beautiful scenery} other{ }}", - "@loadingPhaseLabel": { - "description": "Loading phases", - "placeholders": { - "loadingPhase": {} - } + "wordsToBreakRecord": "Words to break the world record", + "@wordsToBreakRecord": { + "description": "Label for the title regarding words to break the world record" + }, + "getStarted": "Get Started", + "@getStarted": { + "description": "Get started label" } } \ No newline at end of file diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 6d07580a2..30a5c6045 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,17 +1,661 @@ PODS: + - abseil/algorithm (1.20220623.0): + - abseil/algorithm/algorithm (= 1.20220623.0) + - abseil/algorithm/container (= 1.20220623.0) + - abseil/algorithm/algorithm (1.20220623.0): + - abseil/base/config + - abseil/algorithm/container (1.20220623.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/base (1.20220623.0): + - abseil/base/atomic_hook (= 1.20220623.0) + - abseil/base/base (= 1.20220623.0) + - abseil/base/base_internal (= 1.20220623.0) + - abseil/base/config (= 1.20220623.0) + - abseil/base/core_headers (= 1.20220623.0) + - abseil/base/dynamic_annotations (= 1.20220623.0) + - abseil/base/endian (= 1.20220623.0) + - abseil/base/errno_saver (= 1.20220623.0) + - abseil/base/fast_type_id (= 1.20220623.0) + - abseil/base/log_severity (= 1.20220623.0) + - abseil/base/malloc_internal (= 1.20220623.0) + - abseil/base/prefetch (= 1.20220623.0) + - abseil/base/pretty_function (= 1.20220623.0) + - abseil/base/raw_logging_internal (= 1.20220623.0) + - abseil/base/spinlock_wait (= 1.20220623.0) + - abseil/base/strerror (= 1.20220623.0) + - abseil/base/throw_delegate (= 1.20220623.0) + - abseil/base/atomic_hook (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/base (1.20220623.0): + - abseil/base/atomic_hook + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/log_severity + - abseil/base/raw_logging_internal + - abseil/base/spinlock_wait + - abseil/meta/type_traits + - abseil/base/base_internal (1.20220623.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/base/config (1.20220623.0) + - abseil/base/core_headers (1.20220623.0): + - abseil/base/config + - abseil/base/dynamic_annotations (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian (1.20220623.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver (1.20220623.0): + - abseil/base/config + - abseil/base/fast_type_id (1.20220623.0): + - abseil/base/config + - abseil/base/log_severity (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/malloc_internal (1.20220623.0): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/base/prefetch (1.20220623.0): + - abseil/base/config + - abseil/base/pretty_function (1.20220623.0) + - abseil/base/raw_logging_internal (1.20220623.0): + - abseil/base/atomic_hook + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/base/log_severity + - abseil/base/spinlock_wait (1.20220623.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/base/strerror (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/errno_saver + - abseil/base/throw_delegate (1.20220623.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/cleanup/cleanup (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/cleanup/cleanup_internal + - abseil/cleanup/cleanup_internal (1.20220623.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/utility/utility + - abseil/container/common (1.20220623.0): + - abseil/meta/type_traits + - abseil/types/optional + - abseil/container/compressed_tuple (1.20220623.0): + - abseil/utility/utility + - abseil/container/container_memory (1.20220623.0): + - abseil/base/config + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/container/fixed_array (1.20220623.0): + - abseil/algorithm/algorithm + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/throw_delegate + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/container/flat_hash_map (1.20220623.0): + - abseil/algorithm/container + - abseil/base/core_headers + - abseil/container/container_memory + - abseil/container/hash_function_defaults + - abseil/container/raw_hash_map + - abseil/memory/memory + - abseil/container/flat_hash_set (1.20220623.0): + - abseil/algorithm/container + - abseil/base/core_headers + - abseil/container/container_memory + - abseil/container/hash_function_defaults + - abseil/container/raw_hash_set + - abseil/memory/memory + - abseil/container/hash_function_defaults (1.20220623.0): + - abseil/base/config + - abseil/hash/hash + - abseil/strings/cord + - abseil/strings/strings + - abseil/container/hash_policy_traits (1.20220623.0): + - abseil/meta/type_traits + - abseil/container/hashtable_debug_hooks (1.20220623.0): + - abseil/base/config + - abseil/container/hashtablez_sampler (1.20220623.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/stacktrace + - abseil/memory/memory + - abseil/profiling/exponential_biased + - abseil/profiling/sample_recorder + - abseil/synchronization/synchronization + - abseil/utility/utility + - abseil/container/inlined_vector (1.20220623.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/container/inlined_vector_internal + - abseil/memory/memory + - abseil/container/inlined_vector_internal (1.20220623.0): + - abseil/base/core_headers + - abseil/container/compressed_tuple + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/span + - abseil/container/layout (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/types/span + - abseil/utility/utility + - abseil/container/raw_hash_map (1.20220623.0): + - abseil/base/throw_delegate + - abseil/container/container_memory + - abseil/container/raw_hash_set + - abseil/container/raw_hash_set (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/prefetch + - abseil/container/common + - abseil/container/compressed_tuple + - abseil/container/container_memory + - abseil/container/hash_policy_traits + - abseil/container/hashtable_debug_hooks + - abseil/container/hashtablez_sampler + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/utility/utility + - abseil/debugging/debugging_internal (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/errno_saver + - abseil/base/raw_logging_internal + - abseil/debugging/demangle_internal (1.20220623.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/stacktrace (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/debugging/debugging_internal + - abseil/debugging/symbolize (1.20220623.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/debugging_internal + - abseil/debugging/demangle_internal + - abseil/strings/strings + - abseil/functional/any_invocable (1.20220623.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/functional/bind_front (1.20220623.0): + - abseil/base/base_internal + - abseil/container/compressed_tuple + - abseil/meta/type_traits + - abseil/utility/utility + - abseil/functional/function_ref (1.20220623.0): + - abseil/base/base_internal + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/hash/city (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/hash/hash (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/container/fixed_array + - abseil/functional/function_ref + - abseil/hash/city + - abseil/hash/low_level_hash + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/types/optional + - abseil/types/variant + - abseil/utility/utility + - abseil/hash/low_level_hash (1.20220623.0): + - abseil/base/config + - abseil/base/endian + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/memory (1.20220623.0): + - abseil/memory/memory (= 1.20220623.0) + - abseil/memory/memory (1.20220623.0): + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/meta (1.20220623.0): + - abseil/meta/type_traits (= 1.20220623.0) + - abseil/meta/type_traits (1.20220623.0): + - abseil/base/config + - abseil/numeric/bits (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/numeric/int128 (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/numeric/bits + - abseil/numeric/representation (1.20220623.0): + - abseil/base/config + - abseil/profiling/exponential_biased (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/profiling/sample_recorder (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/synchronization/synchronization + - abseil/time/time + - abseil/random/distributions (1.20220623.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/random/internal/distribution_caller + - abseil/random/internal/fast_uniform_bits + - abseil/random/internal/fastmath + - abseil/random/internal/generate_real + - abseil/random/internal/iostream_state_saver + - abseil/random/internal/traits + - abseil/random/internal/uniform_helper + - abseil/random/internal/wide_multiply + - abseil/strings/strings + - abseil/random/internal/distribution_caller (1.20220623.0): + - abseil/base/config + - abseil/base/fast_type_id + - abseil/utility/utility + - abseil/random/internal/fast_uniform_bits (1.20220623.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/random/internal/traits + - abseil/random/internal/fastmath (1.20220623.0): + - abseil/numeric/bits + - abseil/random/internal/generate_real (1.20220623.0): + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/random/internal/fastmath + - abseil/random/internal/traits + - abseil/random/internal/iostream_state_saver (1.20220623.0): + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/random/internal/nonsecure_base (1.20220623.0): + - abseil/base/core_headers + - abseil/container/inlined_vector + - abseil/meta/type_traits + - abseil/random/internal/pool_urbg + - abseil/random/internal/salted_seed_seq + - abseil/random/internal/seed_material + - abseil/types/span + - abseil/random/internal/pcg_engine (1.20220623.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/random/internal/fastmath + - abseil/random/internal/iostream_state_saver + - abseil/random/internal/platform (1.20220623.0): + - abseil/base/config + - abseil/random/internal/pool_urbg (1.20220623.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/random/internal/randen + - abseil/random/internal/seed_material + - abseil/random/internal/traits + - abseil/random/seed_gen_exception + - abseil/types/span + - abseil/random/internal/randen (1.20220623.0): + - abseil/base/raw_logging_internal + - abseil/random/internal/platform + - abseil/random/internal/randen_hwaes + - abseil/random/internal/randen_slow + - abseil/random/internal/randen_engine (1.20220623.0): + - abseil/base/endian + - abseil/meta/type_traits + - abseil/random/internal/iostream_state_saver + - abseil/random/internal/randen + - abseil/random/internal/randen_hwaes (1.20220623.0): + - abseil/base/config + - abseil/random/internal/platform + - abseil/random/internal/randen_hwaes_impl + - abseil/random/internal/randen_hwaes_impl (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/numeric/int128 + - abseil/random/internal/platform + - abseil/random/internal/randen_slow (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/numeric/int128 + - abseil/random/internal/platform + - abseil/random/internal/salted_seed_seq (1.20220623.0): + - abseil/container/inlined_vector + - abseil/meta/type_traits + - abseil/random/internal/seed_material + - abseil/types/optional + - abseil/types/span + - abseil/random/internal/seed_material (1.20220623.0): + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/raw_logging_internal + - abseil/random/internal/fast_uniform_bits + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/random/internal/traits (1.20220623.0): + - abseil/base/config + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/random/internal/uniform_helper (1.20220623.0): + - abseil/base/config + - abseil/meta/type_traits + - abseil/numeric/int128 + - abseil/random/internal/traits + - abseil/random/internal/wide_multiply (1.20220623.0): + - abseil/base/config + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/random/internal/traits + - abseil/random/random (1.20220623.0): + - abseil/random/distributions + - abseil/random/internal/nonsecure_base + - abseil/random/internal/pcg_engine + - abseil/random/internal/pool_urbg + - abseil/random/internal/randen_engine + - abseil/random/seed_sequences + - abseil/random/seed_gen_exception (1.20220623.0): + - abseil/base/config + - abseil/random/seed_sequences (1.20220623.0): + - abseil/base/config + - abseil/random/internal/pool_urbg + - abseil/random/internal/salted_seed_seq + - abseil/random/internal/seed_material + - abseil/random/seed_gen_exception + - abseil/types/span + - abseil/status/status (1.20220623.0): + - abseil/base/atomic_hook + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/base/strerror + - abseil/container/inlined_vector + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/functional/function_ref + - abseil/strings/cord + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/optional + - abseil/status/statusor (1.20220623.0): + - abseil/base/base + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/meta/type_traits + - abseil/status/status + - abseil/strings/strings + - abseil/types/variant + - abseil/utility/utility + - abseil/strings/cord (1.20220623.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/container/fixed_array + - abseil/container/inlined_vector + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/strings/cord_internal + - abseil/strings/cordz_functions + - abseil/strings/cordz_info + - abseil/strings/cordz_statistics + - abseil/strings/cordz_update_scope + - abseil/strings/cordz_update_tracker + - abseil/strings/internal + - abseil/strings/str_format + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/strings/cord_internal (1.20220623.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/base/throw_delegate + - abseil/container/compressed_tuple + - abseil/container/inlined_vector + - abseil/container/layout + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/strings/strings + - abseil/types/span + - abseil/strings/cordz_functions (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/profiling/exponential_biased + - abseil/strings/cordz_handle (1.20220623.0): + - abseil/base/base + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/synchronization/synchronization + - abseil/strings/cordz_info (1.20220623.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/container/inlined_vector + - abseil/debugging/stacktrace + - abseil/strings/cord_internal + - abseil/strings/cordz_functions + - abseil/strings/cordz_handle + - abseil/strings/cordz_statistics + - abseil/strings/cordz_update_tracker + - abseil/synchronization/synchronization + - abseil/types/span + - abseil/strings/cordz_statistics (1.20220623.0): + - abseil/base/config + - abseil/strings/cordz_update_tracker + - abseil/strings/cordz_update_scope (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/strings/cord_internal + - abseil/strings/cordz_info + - abseil/strings/cordz_update_tracker + - abseil/strings/cordz_update_tracker (1.20220623.0): + - abseil/base/config + - abseil/strings/internal (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/meta/type_traits + - abseil/strings/str_format (1.20220623.0): + - abseil/strings/str_format_internal + - abseil/strings/str_format_internal (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/functional/function_ref + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/numeric/representation + - abseil/strings/strings + - abseil/types/optional + - abseil/types/span + - abseil/utility/utility + - abseil/strings/strings (1.20220623.0): + - abseil/base/base + - abseil/base/config + - abseil/base/core_headers + - abseil/base/endian + - abseil/base/raw_logging_internal + - abseil/base/throw_delegate + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/numeric/bits + - abseil/numeric/int128 + - abseil/strings/internal + - abseil/synchronization/graphcycles_internal (1.20220623.0): + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/synchronization/kernel_timeout_internal (1.20220623.0): + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/time/time + - abseil/synchronization/synchronization (1.20220623.0): + - abseil/base/atomic_hook + - abseil/base/base + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/base/dynamic_annotations + - abseil/base/malloc_internal + - abseil/base/raw_logging_internal + - abseil/debugging/stacktrace + - abseil/debugging/symbolize + - abseil/synchronization/graphcycles_internal + - abseil/synchronization/kernel_timeout_internal + - abseil/time/time + - abseil/time (1.20220623.0): + - abseil/time/internal (= 1.20220623.0) + - abseil/time/time (= 1.20220623.0) + - abseil/time/internal (1.20220623.0): + - abseil/time/internal/cctz (= 1.20220623.0) + - abseil/time/internal/cctz (1.20220623.0): + - abseil/time/internal/cctz/civil_time (= 1.20220623.0) + - abseil/time/internal/cctz/time_zone (= 1.20220623.0) + - abseil/time/internal/cctz/civil_time (1.20220623.0): + - abseil/base/config + - abseil/time/internal/cctz/time_zone (1.20220623.0): + - abseil/base/config + - abseil/time/internal/cctz/civil_time + - abseil/time/time (1.20220623.0): + - abseil/base/base + - abseil/base/core_headers + - abseil/base/raw_logging_internal + - abseil/numeric/int128 + - abseil/strings/strings + - abseil/time/internal/cctz/civil_time + - abseil/time/internal/cctz/time_zone + - abseil/types (1.20220623.0): + - abseil/types/any (= 1.20220623.0) + - abseil/types/bad_any_cast (= 1.20220623.0) + - abseil/types/bad_any_cast_impl (= 1.20220623.0) + - abseil/types/bad_optional_access (= 1.20220623.0) + - abseil/types/bad_variant_access (= 1.20220623.0) + - abseil/types/compare (= 1.20220623.0) + - abseil/types/optional (= 1.20220623.0) + - abseil/types/span (= 1.20220623.0) + - abseil/types/variant (= 1.20220623.0) + - abseil/types/any (1.20220623.0): + - abseil/base/config + - abseil/base/core_headers + - abseil/base/fast_type_id + - abseil/meta/type_traits + - abseil/types/bad_any_cast + - abseil/utility/utility + - abseil/types/bad_any_cast (1.20220623.0): + - abseil/base/config + - abseil/types/bad_any_cast_impl + - abseil/types/bad_any_cast_impl (1.20220623.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/types/bad_optional_access (1.20220623.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/types/bad_variant_access (1.20220623.0): + - abseil/base/config + - abseil/base/raw_logging_internal + - abseil/types/compare (1.20220623.0): + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/types/optional (1.20220623.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/memory/memory + - abseil/meta/type_traits + - abseil/types/bad_optional_access + - abseil/utility/utility + - abseil/types/span (1.20220623.0): + - abseil/algorithm/algorithm + - abseil/base/core_headers + - abseil/base/throw_delegate + - abseil/meta/type_traits + - abseil/types/variant (1.20220623.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/base/core_headers + - abseil/meta/type_traits + - abseil/types/bad_variant_access + - abseil/utility/utility + - abseil/utility/utility (1.20220623.0): + - abseil/base/base_internal + - abseil/base/config + - abseil/meta/type_traits - audioplayers_darwin (0.0.1): - FlutterMacOS + - BoringSSL-GRPC (0.0.24): + - BoringSSL-GRPC/Implementation (= 0.0.24) + - BoringSSL-GRPC/Interface (= 0.0.24) + - BoringSSL-GRPC/Implementation (0.0.24): + - BoringSSL-GRPC/Interface (= 0.0.24) + - BoringSSL-GRPC/Interface (0.0.24) + - cloud_firestore (4.15.9): + - Firebase/CoreOnly (~> 10.22.0) + - Firebase/Firestore (~> 10.22.0) + - firebase_core + - FlutterMacOS + - nanopb (< 2.30910.0, >= 2.30908.0) - Firebase/Auth (10.22.0): - Firebase/CoreOnly - FirebaseAuth (~> 10.22.0) - Firebase/CoreOnly (10.22.0): - FirebaseCore (= 10.22.0) - - firebase_auth (4.17.7): + - Firebase/Firestore (10.22.0): + - Firebase/CoreOnly + - FirebaseFirestore (~> 10.22.0) + - firebase_auth (4.17.9): - Firebase/Auth (~> 10.22.0) - Firebase/CoreOnly (~> 10.22.0) - firebase_core - FlutterMacOS - - firebase_core (2.26.0): + - firebase_core (2.27.1): - Firebase/CoreOnly (~> 10.22.0) - FlutterMacOS - FirebaseAppCheckInterop (10.22.0) @@ -26,8 +670,30 @@ PODS: - FirebaseCoreInternal (~> 10.0) - GoogleUtilities/Environment (~> 7.12) - GoogleUtilities/Logger (~> 7.12) + - FirebaseCoreExtension (10.22.0): + - FirebaseCore (~> 10.0) - FirebaseCoreInternal (10.22.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" + - FirebaseFirestore (10.22.0): + - FirebaseCore (~> 10.0) + - FirebaseCoreExtension (~> 10.0) + - FirebaseFirestoreInternal (~> 10.17) + - FirebaseSharedSwift (~> 10.0) + - FirebaseFirestoreInternal (10.22.0): + - abseil/algorithm (~> 1.20220623.0) + - abseil/base (~> 1.20220623.0) + - abseil/container/flat_hash_map (~> 1.20220623.0) + - abseil/memory (~> 1.20220623.0) + - abseil/meta (~> 1.20220623.0) + - abseil/strings/strings (~> 1.20220623.0) + - abseil/time (~> 1.20220623.0) + - abseil/types (~> 1.20220623.0) + - FirebaseAppCheckInterop (~> 10.17) + - FirebaseCore (~> 10.0) + - "gRPC-C++ (~> 1.49.1)" + - leveldb-library (~> 1.22) + - nanopb (< 2.30911.0, >= 2.30908.0) + - FirebaseSharedSwift (10.22.0) - FlutterMacOS (1.0.0) - GoogleUtilities/AppDelegateSwizzler (7.13.0): - GoogleUtilities/Environment @@ -51,7 +717,74 @@ PODS: - GoogleUtilities/Reachability (7.13.0): - GoogleUtilities/Logger - GoogleUtilities/Privacy + - "gRPC-C++ (1.49.1)": + - "gRPC-C++/Implementation (= 1.49.1)" + - "gRPC-C++/Interface (= 1.49.1)" + - "gRPC-C++/Implementation (1.49.1)": + - abseil/base/base (= 1.20220623.0) + - abseil/base/core_headers (= 1.20220623.0) + - abseil/cleanup/cleanup (= 1.20220623.0) + - abseil/container/flat_hash_map (= 1.20220623.0) + - abseil/container/flat_hash_set (= 1.20220623.0) + - abseil/container/inlined_vector (= 1.20220623.0) + - abseil/functional/any_invocable (= 1.20220623.0) + - abseil/functional/bind_front (= 1.20220623.0) + - abseil/functional/function_ref (= 1.20220623.0) + - abseil/hash/hash (= 1.20220623.0) + - abseil/memory/memory (= 1.20220623.0) + - abseil/meta/type_traits (= 1.20220623.0) + - abseil/random/random (= 1.20220623.0) + - abseil/status/status (= 1.20220623.0) + - abseil/status/statusor (= 1.20220623.0) + - abseil/strings/cord (= 1.20220623.0) + - abseil/strings/str_format (= 1.20220623.0) + - abseil/strings/strings (= 1.20220623.0) + - abseil/synchronization/synchronization (= 1.20220623.0) + - abseil/time/time (= 1.20220623.0) + - abseil/types/optional (= 1.20220623.0) + - abseil/types/span (= 1.20220623.0) + - abseil/types/variant (= 1.20220623.0) + - abseil/utility/utility (= 1.20220623.0) + - "gRPC-C++/Interface (= 1.49.1)" + - gRPC-Core (= 1.49.1) + - "gRPC-C++/Interface (1.49.1)" + - gRPC-Core (1.49.1): + - gRPC-Core/Implementation (= 1.49.1) + - gRPC-Core/Interface (= 1.49.1) + - gRPC-Core/Implementation (1.49.1): + - abseil/base/base (= 1.20220623.0) + - abseil/base/core_headers (= 1.20220623.0) + - abseil/container/flat_hash_map (= 1.20220623.0) + - abseil/container/flat_hash_set (= 1.20220623.0) + - abseil/container/inlined_vector (= 1.20220623.0) + - abseil/functional/any_invocable (= 1.20220623.0) + - abseil/functional/bind_front (= 1.20220623.0) + - abseil/functional/function_ref (= 1.20220623.0) + - abseil/hash/hash (= 1.20220623.0) + - abseil/memory/memory (= 1.20220623.0) + - abseil/meta/type_traits (= 1.20220623.0) + - abseil/random/random (= 1.20220623.0) + - abseil/status/status (= 1.20220623.0) + - abseil/status/statusor (= 1.20220623.0) + - abseil/strings/cord (= 1.20220623.0) + - abseil/strings/str_format (= 1.20220623.0) + - abseil/strings/strings (= 1.20220623.0) + - abseil/synchronization/synchronization (= 1.20220623.0) + - abseil/time/time (= 1.20220623.0) + - abseil/types/optional (= 1.20220623.0) + - abseil/types/span (= 1.20220623.0) + - abseil/types/variant (= 1.20220623.0) + - abseil/utility/utility (= 1.20220623.0) + - BoringSSL-GRPC (= 0.0.24) + - gRPC-Core/Interface (= 1.49.1) + - gRPC-Core/Interface (1.49.1) - GTMSessionFetcher/Core (3.3.1) + - leveldb-library (1.22.4) + - nanopb (2.30909.1): + - nanopb/decode (= 2.30909.1) + - nanopb/encode (= 2.30909.1) + - nanopb/decode (2.30909.1) + - nanopb/encode (2.30909.1) - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS @@ -59,6 +792,7 @@ PODS: DEPENDENCIES: - audioplayers_darwin (from `Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/macos`) + - cloud_firestore (from `Flutter/ephemeral/.symlinks/plugins/cloud_firestore/macos`) - firebase_auth (from `Flutter/ephemeral/.symlinks/plugins/firebase_auth/macos`) - firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`) - FlutterMacOS (from `Flutter/ephemeral`) @@ -66,18 +800,30 @@ DEPENDENCIES: SPEC REPOS: trunk: + - abseil + - BoringSSL-GRPC - Firebase - FirebaseAppCheckInterop - FirebaseAuth - FirebaseCore + - FirebaseCoreExtension - FirebaseCoreInternal + - FirebaseFirestore + - FirebaseFirestoreInternal + - FirebaseSharedSwift - GoogleUtilities + - "gRPC-C++" + - gRPC-Core - GTMSessionFetcher + - leveldb-library + - nanopb - PromisesObjC EXTERNAL SOURCES: audioplayers_darwin: :path: Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/macos + cloud_firestore: + :path: Flutter/ephemeral/.symlinks/plugins/cloud_firestore/macos firebase_auth: :path: Flutter/ephemeral/.symlinks/plugins/firebase_auth/macos firebase_core: @@ -88,17 +834,28 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin SPEC CHECKSUMS: + abseil: 926fb7a82dc6d2b8e1f2ed7f3a718bce691d1e46 audioplayers_darwin: dcad41de4fbd0099cb3749f7ab3b0cb8f70b810c + BoringSSL-GRPC: 3175b25143e648463a56daeaaa499c6cb86dad33 + cloud_firestore: 0208417c313dbfa1a084ef8f9bdad9fd5ec676ff Firebase: 797fd7297b7e1be954432743a0b3f90038e45a71 - firebase_auth: 7c693e2314a8b2cd8b925d8e8a4c15f8883863ce - firebase_core: 2dd24517c818d09543dffe1b74daa16fb3f55a81 + firebase_auth: c3804eee5fa773900d3ea874bc14bbe64594e89a + firebase_core: cb81862138b1b98a890bcf3ee59ec820dad075b9 FirebaseAppCheckInterop: 58db3e9494751399cf3e7b7e3e705cff71099153 FirebaseAuth: bbe4c68f958504ba9e54aee181adbdf5b664fbc6 FirebaseCore: 0326ec9b05fbed8f8716cddbf0e36894a13837f7 + FirebaseCoreExtension: 6394c00b887d0bebadbc7049c464aa0cbddc5d41 FirebaseCoreInternal: bca337352024b18424a61e478460547d46c4c753 + FirebaseFirestore: 16cb8a85fc29da272deaed22a101e24703251da9 + FirebaseFirestoreInternal: 86fe6fc8ca156309cb4842d2d7b2f15c669a64a0 + FirebaseSharedSwift: 48076404e6e52372290d15a07d2ed1d2f1754023 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 GoogleUtilities: d053d902a8edaa9904e1bd00c37535385b8ed152 + "gRPC-C++": 2df8cba576898bdacd29f0266d5236fa0e26ba6a + gRPC-Core: a21a60aefc08c68c247b439a9ef97174b0c54f96 GTMSessionFetcher: 8a1b34ad97ebe6f909fb8b9b77fba99943007556 + leveldb-library: 06a69cc7582d64b29424a63e085e683cc188230a + nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5 path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 diff --git a/packages/io_crossword_ui/lib/src/theme/io_crossword_theme.dart b/packages/io_crossword_ui/lib/src/theme/io_crossword_theme.dart index c3a21328c..37edc5342 100644 --- a/packages/io_crossword_ui/lib/src/theme/io_crossword_theme.dart +++ b/packages/io_crossword_ui/lib/src/theme/io_crossword_theme.dart @@ -11,11 +11,7 @@ class IoCrosswordTheme { return ThemeData( useMaterial3: true, colorScheme: _colorScheme, - textTheme: _textTheme.apply( - bodyColor: IoCrosswordColors.seedWhite, - displayColor: IoCrosswordColors.seedWhite, - decorationColor: IoCrosswordColors.seedWhite, - ), + textTheme: _textTheme, ); } diff --git a/packages/io_crossword_ui/lib/src/widgets/io_crossword_card.dart b/packages/io_crossword_ui/lib/src/widgets/io_crossword_card.dart index 612dc767a..80e059d1c 100644 --- a/packages/io_crossword_ui/lib/src/widgets/io_crossword_card.dart +++ b/packages/io_crossword_ui/lib/src/widgets/io_crossword_card.dart @@ -31,7 +31,10 @@ class IoCrosswordCard extends StatelessWidget { child: Material( type: MaterialType.card, borderRadius: BorderRadius.circular(24), - child: SizedBox.expand(child: child), + child: Padding( + padding: const EdgeInsets.all(24), + child: SizedBox.expand(child: child), + ), ), ), ); diff --git a/packages/io_crossword_ui/lib/src/widgets/primary_button.dart b/packages/io_crossword_ui/lib/src/widgets/primary_button.dart new file mode 100644 index 000000000..484260648 --- /dev/null +++ b/packages/io_crossword_ui/lib/src/widgets/primary_button.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; + +/// {@template primary_button} +/// A primary button. +/// {@endtemplate} +class PrimaryButton extends StatelessWidget { + /// {@macro primary_button} + const PrimaryButton({ + required this.onPressed, + required this.label, + super.key, + }); + + /// The callback called when the button is tapped. + final VoidCallback onPressed; + + /// The text to display in the button. + final String label; + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + height: 48, + child: FilledButton( + onPressed: onPressed, + child: Text(label), + ), + ); + } +} diff --git a/packages/io_crossword_ui/lib/src/widgets/widgets.dart b/packages/io_crossword_ui/lib/src/widgets/widgets.dart index 695410029..eac29b578 100644 --- a/packages/io_crossword_ui/lib/src/widgets/widgets.dart +++ b/packages/io_crossword_ui/lib/src/widgets/widgets.dart @@ -1 +1,2 @@ export 'io_crossword_card.dart'; +export 'primary_button.dart'; diff --git a/packages/io_crossword_ui/test/src/helpers/helpers.dart b/packages/io_crossword_ui/test/src/helpers/helpers.dart new file mode 100644 index 000000000..b15fe650a --- /dev/null +++ b/packages/io_crossword_ui/test/src/helpers/helpers.dart @@ -0,0 +1 @@ +export 'pump_app.dart'; diff --git a/packages/io_crossword_ui/test/src/helpers/pump_app.dart b/packages/io_crossword_ui/test/src/helpers/pump_app.dart new file mode 100644 index 000000000..c2252fd7d --- /dev/null +++ b/packages/io_crossword_ui/test/src/helpers/pump_app.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +extension PumpApp on WidgetTester { + Future pumpApp(Widget widget) { + return pumpWidget( + MaterialApp(home: widget), + ); + } +} diff --git a/packages/io_crossword_ui/test/src/widgets/primary_button_test.dart b/packages/io_crossword_ui/test/src/widgets/primary_button_test.dart new file mode 100644 index 000000000..fc10bf638 --- /dev/null +++ b/packages/io_crossword_ui/test/src/widgets/primary_button_test.dart @@ -0,0 +1,35 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:io_crossword_ui/io_crossword_ui.dart'; + +import '../helpers/helpers.dart'; + +void main() { + group('PrimaryButton', () { + testWidgets('renders label', (tester) async { + await tester.pumpApp( + PrimaryButton( + onPressed: () {}, + label: 'Label', + ), + ); + + expect(find.text('Label'), findsOneWidget); + }); + + testWidgets('tapping triggers onPressed', (tester) async { + var value = 0; + await tester.pumpApp( + PrimaryButton( + onPressed: () { + value++; + }, + label: 'Label', + ), + ); + + await tester.tap(find.byType(PrimaryButton)); + + expect(value, 1); + }); + }); +} diff --git a/test/game_intro/view/welcome_view_test.dart b/test/game_intro/view/welcome_view_test.dart index 8710300f5..87fded86d 100644 --- a/test/game_intro/view/welcome_view_test.dart +++ b/test/game_intro/view/welcome_view_test.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:io_crossword/game_intro/game_intro.dart'; +import 'package:io_crossword_ui/io_crossword_ui.dart'; import 'package:mocktail/mocktail.dart'; import '../../helpers/helpers.dart'; @@ -24,13 +25,23 @@ void main() { ); }); + testWidgets( + 'renders the record progress', + (tester) async { + when(() => bloc.state).thenReturn(const GameIntroState()); + await tester.pumpApp(child); + + expect(find.byType(RecordProgress), findsOneWidget); + }, + ); + testWidgets( 'adds WelcomeCompleted event when tapping button', (tester) async { when(() => bloc.state).thenReturn(const GameIntroState()); await tester.pumpApp(child); - await tester.tap(find.byType(ElevatedButton)); + await tester.tap(find.byType(PrimaryButton)); verify(() => bloc.add(const WelcomeCompleted())).called(1); },