Skip to content

Commit

Permalink
feat: accessibility pickers and v2.0.0 (#209)
Browse files Browse the repository at this point in the history
* refactor!: remove deprecated code

* chore(example): update windows and linux runners in the example

* feat(example): use open-moji instead of emoji one in the example

* refactor: remove leftovers

* chore(deps)!: bump flutter version to v3.19.0

* feat(ui): added semantic-related features to the tiles

* docs: provided documentation for v2.0.0
  • Loading branch information
tsinis authored Aug 4, 2024
1 parent 5ecf18f commit 5f539da
Show file tree
Hide file tree
Showing 56 changed files with 208 additions and 1,301 deletions.
5 changes: 4 additions & 1 deletion .vscode/sealed_world.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
}
},
"cSpell.words": [
"Appium",
"Automator",
"Bhojpuri",
"CBDT",
"Cinis",
Expand All @@ -105,7 +107,8 @@
"taeguk",
"Taegukgi",
"twemoji",
"umpirsky"
"umpirsky",
"XCUI"
],
"cSpell.useGitignore": true,
"cSpell.ignorePaths": [
Expand Down
21 changes: 21 additions & 0 deletions packages/world_countries/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
## 2.0.0

BREAKING CHANGES

- Package requires Flutter version 3.19+, because it now uses Semantics [identifier](https://api.flutter.dev/flutter/semantics/SemanticsData/identifier.html) property in all picker's tiles (this property was introduced in that SDK version). This identifier describes the node for UI automation tools that work by querying the accessibility hierarchy, such as Android UI Automator, iOS XCUITest, or Appium. It's not exposed to users.
- All previously deprecated code, marked with the @Deprecated annotation, has been removed. Including color font emojis (you can still use them on your own via `EmojiFlag.custom` constructor, example code is provided in the `example` project).

NEW FEATURES

- All pickers are updated with accessibility in mind, ensuring seamless integration with screen readers and assistive technologies. Feel free to use [SemanticsDebugger](https://api.flutter.dev/flutter/widgets/SemanticsDebugger-class.html) to check it.
- `CountryFlag` now offers `alternativeMap` parameter that you can use to provide alternative look of the country flag. By default it contains updated Afghanistan flag (with official design from year 2021) and alternative French Guiana flags.
- `CountryFlag` now have non-required child property.

REFACTOR

- New asserts in the constructors and optimizations in several country flag painters.

TESTS

- Added tests for new flag asserts and update goldens with arabic fonts.

## 1.6.0

NEW FEATURES
Expand Down
54 changes: 6 additions & 48 deletions packages/world_countries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ This ISO-driven and fully tested package provides information about world countr
- [Data](#data)
- [Additional information](#additional-information)
- [References and credits](#references-and-credits)
- [Attributions](#attributions)
- [FAQ](#faq)

### Features
Expand All @@ -48,7 +47,7 @@ To preview the demo from the example, you can visit [this web page](https://tsin
### Getting started

To use this package, you will need Flutter version 3.10+. Add `world_countries` as a dependency in your `pubspec.yaml` file.
To use this package, you will need Flutter version 3.19+. Add `world_countries` as a dependency in your `pubspec.yaml` file.

```yaml
dependencies:
Expand Down Expand Up @@ -221,59 +220,14 @@ If you have any issues or suggestions for the package, please file them in the G

This package is licensed under the MIT license. See [LICENSE](./LICENSE) for details. This package dependencies are under their respective licenses (that can be found in their respective folders under LICENSE and NOTICE files).

### Attributions

The color emoji flags fonts used in this package were obtained from open-source repositories of the original creators. The fonts are redistributed under the terms of the licenses offered by the original authors. The fonts sizes were reduced, by removing non-flag glyphs, to reduce the package size and to reduce the copyright footprint, since most of the country flags are in Public Domain. No modifications in graphic itself were made.

#### Noto Emoji fonts

The [Noto Emoji font](./lib/assets/fonts/NotoEmoji/) font comes from [Noto Emoji](https://github.com/googlefonts/noto-emoji) emoji library. Noto Emoji fonts are under the [SIL Open Font License, version 1.1](https://scripts.sil.org/OFL).

#### OpenMoji fonts

The [OpenMoji](./lib/assets/fonts/OpenMoji/) font comes from [OpenMoji](https://github.com/hfg-gmuend/openmoji) project and redistributed under the CC-BY-SA-4.0 [license terms](https://creativecommons.org/licenses/by-sa/4.0/).

#### Twemoji fonts

The [Twemoji font in COLR/CPAL layered format](./lib/assets/fonts/Twemoji/) font comes from [Twemoji-COLR](https://github.com/mozilla/twemoji-colr) project (Mozilla's COLR/CPAL version of [Twemoji](https://github.com/twitter/twemoji)). Twemoji graphics made by Twitter and other contributors
and is used and redistributed under the CC-BY-4.0 [license terms](https://creativecommons.org/licenses/by/4.0) offered by the Twemoji project.

---

### FAQ

#### I have problems rendering COLR emoji flags on Android

Answer: Android OS [supports](https://developer.android.com/about/versions/13/features#color-vector-fonts) COLRv1 fonts from version 13 on (API level 33).

#### My flags on web platform are grey (not colored)

Answer: Please add `useColorEmoji: true` parameter to your `engineInitializer.initializeEngine` method ([index.html](https://github.com/flutter/flutter/issues/119536#issuecomment-1546247494)).

#### Looks like tree shaking of unused emoji flags is not working on web

Answer: Yes it's know Flutter's [issue](https://github.com/flutter/flutter/issues/64106). Although all font families together are not that big, every single KB might be crucial for a web-page loading times. Run this from your project's root directory:

```shell
dart run world_countries:clean_build [--keep twemoji,notoemoji,openmoji]
```

You can specify which emoji family you want to keep with the optional `--keep` parameter.

#### I don't like default tiles UI in the pickers

Answer: Every picker has a `itemBuilder` parameter, providing access to specific list item properties, for example this is how you can show only a common country name in `CountryPicker`:

```dart
CountryPicker(
itemBuilder: (country, {isDense}) => Text(country.item.name.common),
);
```

#### How can I change emoji flag from default Twemoji to something else?

Answer: You can create your own `itemBuilder` with use of `EmojiFlag` widget that has multiple named constructors and only require country instance, to show different type of flag:

```dart
CountryPicker(
itemBuilder: (country, {isDense}) => EmojiFlag.platformDefault(country.item),
Expand All @@ -282,10 +236,14 @@ CountryPicker(

#### Why should I use this package over any other country/currency/language picker package?

- **Fully Accessible**: All pickers are meticulously crafted with accessibility in mind, ensuring seamless integration with screen readers and assistive technologies.
- **Every flag is a Widget**: This package doesn't use heavy SVG or any other assets to show country flags in the pickers. All flags are declarative-style optimized CustomPainters. That means that you don't have to worry about pre-caching, increased app size, platform-dependent look of the flags, etc. And since it's a widget - you can always change its look - shape, decoration, aspect ratio, etc. Just ask yourself for example - how you can easily change the aspect ratio of asset-based flags without stretching/shrinking them.
- **Up-to-date Flags**: This package ensures accurate and timely flag representations, reflecting current designs. Unlike other packages or emoji/font sets that often use outdated flags, this package offers flags with the most recent designs (such as the Afghan flag from 2013 is shown here correctly with a design from year 2021).
- **Sealed classes**: This package provides data in the form of sealed classes, allowing you to create your own instances and work with them as with existing ones (for example this is not possible with enums or regular classes (without losing it's sealed nature), you can also override existing or add new data, etc.).
- **No 3rd-party dependencies**: This package has no third-party dependencies, ensuring that you won't have any issues or conflicts with other dependencies (no even `meta` here, because of that).
- **Rich data**: This package offers far more data than any other package + tons of translations (all [GlobalMaterialLocalizations](https://api.flutter.dev/flutter/flutter_localizations/GlobalMaterialLocalizations-class.html) and [GlobalCupertinoLocalizations](https://api.flutter.dev/flutter/flutter_localizations/GlobalCupertinoLocalizations-class.html) locales and more).
- **Type-safe**: The contracts and types in this package are very strong, ensuring that your code is strongly typed and well-defined.
- **High code coverage**: The code in this package has almost 100% code coverage, with more than 130 (+3819 in underling Dart packages) tests, providing confidence in its reliability and stability.
- **High code coverage**: The code in this package boasts nearly 100% test coverage, with almost 4,000 tests (130+ in this package, 3828+ in underlying Dart packages) ensuring reliability and stability.
- **Comprehensive Documentation**: This package provides full documentation for every non-code generated public member, usually with examples, ensuring clarity and ease of use.
- **Industry adopted**: This package is actively used in production by numerous European companies, ensuring its efficacy and robustness in real-world scenarios.
- **MIT License**: This package and sources are released under the MIT license, which is a permissive license that allows users to use, modify, and distribute the code with minimal restrictions. The MIT license is considered better than most other open-source licenses because it provides flexibility and allows users to incorporate the code into their projects without worrying about legal implications.
12 changes: 0 additions & 12 deletions packages/world_countries/bin/clean_build.dart

This file was deleted.

71 changes: 0 additions & 71 deletions packages/world_countries/bin/cli/build_cleaner.dart

This file was deleted.

Binary file modified packages/world_countries/doc/example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/world_countries/doc/structure.webp
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/world_countries/example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ This project includes code from the [Flutter samples: Navigation and Routing](ht

Please see the original [LICENSE](./lib/routing/LICENSE) and [AUTHORS](./lib/routing/AUTHORS) files for the full text of the BSD 3-Clause License and original authors list.

This project using [EmojiOne Fonts](https://github.com/adobe-fonts/emojione-color) as an example. You can read more about it in the [fonts/EmojiOne](./assets/fonts/EmojiOne/) directory.
This project using [OpenMoji Fonts](https://github.com/hfg-gmuend/openmoji) as an example of custom `EmojiFlag` usage. You can read more about it and it's license in the [fonts/OpenMoji](./assets/fonts/OpenMoji/) directory.

## License

Expand Down
Binary file not shown.
Binary file not shown.

This file was deleted.

This file was deleted.

Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## OpenMoji Fonts

The OpenMoji font comes from [OpenMoji](https://github.com/hfg-gmuend/openmoji) project and redistributed under the CC-BY-SA-4.0 [license terms](https://creativecommons.org/licenses/by-sa/4.0/).
9 changes: 8 additions & 1 deletion packages/world_countries/example/lib/assets/assets.gen.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 4 additions & 7 deletions packages/world_countries/example/lib/assets/fonts.gen.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions packages/world_countries/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ class _MainState extends State<Main> {
/// [CountryTileThemeData].
static const pickerThemes = <ThemeExtension>[
PickersThemeData(primary: true), // Applies to all types of pickers.
/// Specify the flag decoration in the default country/phone-code picker.
FlagThemeData(
decoration:
BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(4))),
/// Specify the flag decoration in the default country/phone-code picker.
decoration: BoxDecoration(border: Border.fromBorderSide(BorderSide())),
),
];
final _navigatorKey = GlobalKey<NavigatorState>();
Expand All @@ -49,6 +48,7 @@ class _MainState extends State<Main> {
Widget build(BuildContext context) => RouteStateScope(
notifier: _routeState,
child: MaterialApp.router(
debugShowCheckedModeBanner: false,
routeInformationParser: _routeParser,
routerDelegate: _routerDelegate,
theme: ThemeData(
Expand Down
17 changes: 15 additions & 2 deletions packages/world_countries/example/lib/tabs/country_tab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import "package:flutter/material.dart";
import "package:world_countries/world_countries.dart";

import "../assets/fonts.gen.dart";
import "../model/world_data.dart";
import "../widgets/abstractions/world_data_tab.dart";
import "../widgets/description_tile.dart";
Expand Down Expand Up @@ -39,8 +40,20 @@ final class CountryTab extends WorldDataTab<WorldCountry> {
),
],
),
titleOverlay:
AbsorbPointer(child: EmojiFlag.platformDefault(data, size: 136)),
titleOverlay: AbsorbPointer(
child: EmojiFlag.custom(
data,
size: 148,
style: TextStyle(
fontFamily: FunctionalPlatform.maybeWhenConst(
iOS: FontFamily.openMojiCOLR0,
macOS: FontFamily.openMojiCOLR0,
windows: FontFamily.openMojiCOLR0,
orElse: FontFamily.openMojiCOLR1,
),
),
),
),
titlePadding: const EdgeInsets.only(top: 80, bottom: 8),
titleMargin: const EdgeInsets.only(top: 100),
children: <DescriptionTile>[
Expand Down
6 changes: 6 additions & 0 deletions packages/world_countries/example/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
COMPONENT Runtime)
endforeach(bundled_library)

# Copy the native assets provided by the build.dart from all packages.
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)

# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
Expand Down
20 changes: 20 additions & 0 deletions packages/world_countries/example/linux/my_application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@ static gboolean my_application_local_command_line(GApplication* application, gch
return TRUE;
}

// Implements GApplication::startup.
static void my_application_startup(GApplication* application) {
//MyApplication* self = MY_APPLICATION(object);

// Perform any actions required at application startup.

G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
}

// Implements GApplication::shutdown.
static void my_application_shutdown(GApplication* application) {
//MyApplication* self = MY_APPLICATION(object);

// Perform any actions required at application shutdown.

G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
}

// Implements GObject::dispose.
static void my_application_dispose(GObject* object) {
MyApplication* self = MY_APPLICATION(object);
Expand All @@ -91,6 +109,8 @@ static void my_application_dispose(GObject* object) {
static void my_application_class_init(MyApplicationClass* klass) {
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
G_APPLICATION_CLASS(klass)->startup = my_application_startup;
G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
}

Expand Down
Loading

0 comments on commit 5f539da

Please sign in to comment.