Skip to content

Commit

Permalink
feat: flag extensions (#211)
Browse files Browse the repository at this point in the history
* feat(helpers): added new flag extensions on country

* test(helpers): added tests for new getters

* docs: provide documentation for v1.1.0

* refactor: general refactoring in flutter packages and tests

* feat(ui): improvements in world_countries example

* chore(deps): bump fujidaiti/dart-package-inspector

* chore(test): update goldens

---------

Co-authored-by: Cirrus CI <[email protected]>
  • Loading branch information
tsinis and Cirrus CI authored Aug 6, 2024
1 parent 1d6b9be commit baa3e35
Show file tree
Hide file tree
Showing 617 changed files with 302 additions and 178 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/verify_package_workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:

- name: 📈 Check Pub score
if: ${{ github.event_name == 'pull_request' }}
uses: fujidaiti/[email protected].2
uses: fujidaiti/[email protected].3
with:
report: ${{ steps.analysis.outputs.json_output }}
min-pub-points: 130
Expand Down
6 changes: 3 additions & 3 deletions packages/_sealed_world_tests/lib/tests/advanced_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const _defaultRetryCount = 1; // For performance tests.
void performanceTest(
String description,
// ignore: avoid-dynamic, strict_raw_type, it's a copy of regular test method.
FutureOr Function() body, {
FutureOr<void> Function() body, {
num durationLimit = _defaultDurationLimitInMs,
String? testOn,
Timeout? timeout,
Expand All @@ -42,7 +42,7 @@ void randomElementTest<T extends Object>(
String description,
Iterable<T> iterable,
// ignore: avoid-dynamic, strict_raw_type, it's a copy of regular test method.
FutureOr Function(T) body, {
FutureOr<void> Function(T) body, {
num durationLimit = _defaultDurationLimitInMs,
String? testOn,
Timeout? timeout,
Expand Down Expand Up @@ -75,7 +75,7 @@ void assertTest(
Object? Function() createInstance, {
bool shouldThrow = true,
// ignore: avoid-dynamic, strict_raw_type, it's a copy of regular test method.
FutureOr Function()? alsoExpect,
FutureOr<void> Function()? alsoExpect,
String? testOn,
Timeout? timeout,
Object? skip,
Expand Down
1 change: 1 addition & 0 deletions packages/world_countries/example/lib/app_navigator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class AppNavigator extends StatelessWidget {
child: MainPage(parsed, navigate: routeState.go),
),
],
// ignore: deprecated_member_use, TODO!
onPopPage: (route, result) => route.didPop(result),
);
}
Expand Down
20 changes: 7 additions & 13 deletions packages/world_countries/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import "model/world_data.dart";
import "routing/delegate.dart";
import "routing/parser.dart";
import "routing/route_state.dart";
import "theme/color_schemes.g.dart";
import "theme/theme_manager.dart";
import "theme/theme_switcher.dart";

void main() => runApp(const Main());
void main() => runApp(const ThemeManager(child: Main()));

class Main extends StatefulWidget {
const Main({super.key});
Expand All @@ -21,13 +22,14 @@ class Main extends StatefulWidget {
class _MainState extends State<Main> {
/// Also [CurrencyTileThemeData], [LanguageTileThemeData],
/// [CountryTileThemeData].
static const pickerThemes = <ThemeExtension>[
static const extensions = <ThemeExtension>[
PickersThemeData(primary: true), // Applies to all types of pickers.
FlagThemeData(
/// Specify the flag decoration in the default country/phone-code picker.
decoration: BoxDecoration(border: Border.fromBorderSide(BorderSide())),
),
];

final _navigatorKey = GlobalKey<NavigatorState>();
final _routeParser = TemplateRouteParser(allowedPaths: WorldData.paths);
late final _routeState = RouteState(_routeParser);
Expand All @@ -51,16 +53,8 @@ class _MainState extends State<Main> {
debugShowCheckedModeBanner: false,
routeInformationParser: _routeParser,
routerDelegate: _routerDelegate,
theme: ThemeData(
extensions: pickerThemes,
useMaterial3: true,
colorScheme: lightColorScheme,
),
darkTheme: ThemeData(
extensions: pickerThemes,
useMaterial3: true,
colorScheme: darkColorScheme,
),
theme:
ThemeProvider.of(context)?.theme.copyWith(extensions: extensions),
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
Expand Down
33 changes: 22 additions & 11 deletions packages/world_countries/example/lib/pages/main_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ import "../tabs/country_tab.dart";
import "../tabs/currency_tab.dart";
import "../tabs/language_tab.dart";
import "../tabs/tabs_data_controller.dart";
import "../theme/theme_switcher.dart";
import "../widgets/abstractions/world_data_tab.dart";
import "../widgets/floating_button.dart";
import "../widgets/menu_button.dart";

class MainPage extends StatefulWidget {
MainPage(ParsedData data, {AsyncValueSetter<String>? navigate, super.key})
: _dataType = data.value,
_country = CountryTab(data.country, navigate),
_currency = CurrencyTab(data.currency, navigate),
_lang = LanguageTab(data.language, navigate);
MainPage(this._data, {AsyncValueSetter<String>? navigate, super.key})
: _country = CountryTab(_data.country, navigate),
_currency = CurrencyTab(_data.currency, navigate),
_lang = LanguageTab(_data.language, navigate);

final ParsedData _data;

final WorldData _dataType;
final WorldDataTab<WorldCountry> _country;
final WorldDataTab<FiatCurrency> _currency;
final WorldDataTab<NaturalLanguage> _lang;
Expand All @@ -35,7 +37,17 @@ class MainPage extends StatefulWidget {

class _MainPageState extends State<MainPage>
with SingleTickerProviderStateMixin {
late final _controller = TabsDataController(widget._dataType, vsync: this);
late final _controller = TabsDataController(widget._data.value, vsync: this);

@override
void didUpdateWidget(MainPage oldWidget) {
super.didUpdateWidget(oldWidget);
WidgetsBinding.instance.addPostFrameCallback(
(_) => ThemeProvider.of(context)?.changeColors?.call(
flagPropertiesMap[widget._data.country],
),
);
}

FutureOr<void> _onFabPressed({bool isLong = false}) {
final pick = widget._mapPickers(_controller.currentData);
Expand Down Expand Up @@ -74,14 +86,13 @@ class _MainPageState extends State<MainPage>
onLongPress: _onAppBarSearchPressed,
child: IconButton(
onPressed: controller.openView,
icon: const Icon(
Icons.search,
semanticLabel: "search_icon",
),
icon:
const Icon(Icons.search, semanticLabel: "search_icon"),
),
),
suggestionsBuilder: _anchorPicker,
),
const MenuButton(),
],
bottom: TabBar(
tabs: List.unmodifiable(
Expand Down
11 changes: 0 additions & 11 deletions packages/world_countries/example/lib/theme/README.md

This file was deleted.

69 changes: 0 additions & 69 deletions packages/world_countries/example/lib/theme/color_schemes.g.dart

This file was deleted.

26 changes: 26 additions & 0 deletions packages/world_countries/example/lib/theme/theme_manager.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import "package:flutter/material.dart";
import "package:world_countries/world_countries.dart";

import "theme_switcher.dart";

class ThemeManager extends StatefulWidget {
const ThemeManager({required this.child, super.key});

final Widget child;

@override
State<ThemeManager> createState() => _ThemeManagerState();
}

class _ThemeManagerState extends State<ThemeManager> {
FlagProperties? _properties;

void _onChange(FlagProperties? newProperties) =>
setState(() => _properties = newProperties);
@override
Widget build(BuildContext context) => ThemeProvider(
_properties,
changeColors: _onChange,
child: widget.child,
);
}
48 changes: 48 additions & 0 deletions packages/world_countries/example/lib/theme/theme_switcher.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import "package:flutter/material.dart";
import "package:world_countries/world_countries.dart";

class ThemeProvider extends InheritedWidget {
const ThemeProvider(
this._flagProperties, {
required super.child,
this.changeColors,
super.key,
});

static const _whiteColor = Colors.white;
final FlagProperties? _flagProperties;
final ValueSetter<FlagProperties?>? changeColors;

Iterable<Color>? _maybeStripeColors(FlagProperties? flagProperties) =>
flagProperties?.stripeColors.map((stripe) => stripe.color);

@override
bool updateShouldNotify(ThemeProvider oldWidget) {
final oldSeed = _maybeStripeColors(oldWidget._flagProperties)?.firstOrNull;
final newSeed = _maybeStripeColors(_flagProperties)?.firstOrNull;

return newSeed != oldSeed;
}

static ThemeProvider? of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<ThemeProvider>();

ThemeData get theme {
final stripeColors = _maybeStripeColors(_flagProperties);
final seedColor = stripeColors?.first.withOpacity(1) ?? _whiteColor;
final isDark =
ThemeData.estimateBrightnessForColor(seedColor) == Brightness.dark;

return ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: seedColor,
secondary: stripeColors?.elementAtOrNull(1),
primary: stripeColors?.elementAtOrNull(2),
),
floatingActionButtonTheme: FloatingActionButtonThemeData(
backgroundColor: seedColor,
foregroundColor: isDark ? _whiteColor : Colors.black,
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ class FloatingButton extends StatelessWidget {
Widget build(BuildContext context) => GestureDetector(
onLongPress: () => onPressed(isLong: true),
child: FloatingActionButton(
foregroundColor: context.theme.colorScheme.onTertiary,
backgroundColor: context.theme.colorScheme.tertiary,
onPressed: () => onPressed(isLong: false),
child: AnimatedBuilder(
animation: controller,
Expand Down
29 changes: 29 additions & 0 deletions packages/world_countries/example/lib/widgets/menu_button.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import "package:flutter/material.dart";

class MenuButton extends StatelessWidget {
const MenuButton({super.key});

@override
Widget build(BuildContext context) => PopupMenuButton<String>(
itemBuilder: (_) => const [
PopupMenuItem(
child: Align(
alignment: Alignment.centerRight,
child: Text("Feedback"),
),
),
PopupMenuItem(
child: Align(
alignment: Alignment.centerRight,
child: Text("Settings"),
),
),
PopupMenuItem(
child: Align(
alignment: Alignment.centerRight,
child: Text("About"),
),
),
],
);
}
Loading

0 comments on commit baa3e35

Please sign in to comment.