fixed localizations issues
changed application name updated svg icons
This commit is contained in:
parent
a676d454ca
commit
04120c4847
@ -1,6 +1,6 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:label="flutter_android_app"
|
||||
android:label="Crypto Exchange"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
|
@ -1,5 +1,19 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-ru" viewBox="0 0 640 480">
|
||||
<path fill="#fff" d="M0 0h640v160H0z"/>
|
||||
<path fill="#0039a6" d="M0 160h640v160H0z"/>
|
||||
<path fill="#d52b1e" d="M0 320h640v160H0z"/>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 -4 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_503_2726)">
|
||||
<rect x="0.25" y="0.25" width="27.5" height="19.5" rx="1.75" fill="white" stroke="#F5F5F5" stroke-width="0.5"/>
|
||||
<mask id="mask0_503_2726" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="28" height="20">
|
||||
<rect x="0.25" y="0.25" width="27.5" height="19.5" rx="1.75" fill="white" stroke="white" stroke-width="0.5"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_503_2726)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 13.3333H28V6.66667H0V13.3333Z" fill="#0C47B7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 20H28V13.3333H0V20Z" fill="#E53B35"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_503_2726">
|
||||
<rect width="28" height="20" rx="2" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 225 B After Width: | Height: | Size: 968 B |
@ -1,9 +1,34 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-us" viewBox="0 0 640 480">
|
||||
<path fill="#bd3d44" d="M0 0h640v480H0"/>
|
||||
<path stroke="#fff" stroke-width="37" d="M0 55.3h640M0 129h640M0 203h640M0 277h640M0 351h640M0 425h640"/>
|
||||
<path fill="#192f5d" d="M0 0h364.8v258.5H0"/>
|
||||
<marker id="us-a" markerHeight="30" markerWidth="30">
|
||||
<path fill="#fff" d="m14 0 9 27L0 10h28L5 27z"/>
|
||||
</marker>
|
||||
<path fill="none" marker-mid="url(#us-a)" d="m0 0 16 11h61 61 61 61 60L47 37h61 61 60 61L16 63h61 61 61 61 60L47 89h61 61 60 61L16 115h61 61 61 61 60L47 141h61 61 60 61L16 166h61 61 61 61 60L47 192h61 61 60 61L16 218h61 61 61 61 60z"/>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 -4 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_503_3486)">
|
||||
<rect width="28" height="20" rx="2" fill="white"/>
|
||||
<mask id="mask0_503_3486" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="28" height="20">
|
||||
<rect width="28" height="20" rx="2" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_503_3486)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M28 0H0V1.33333H28V0ZM28 2.66667H0V4H28V2.66667ZM0 5.33333H28V6.66667H0V5.33333ZM28 8H0V9.33333H28V8ZM0 10.6667H28V12H0V10.6667ZM28 13.3333H0V14.6667H28V13.3333ZM0 16H28V17.3333H0V16ZM28 18.6667H0V20H28V18.6667Z" fill="#D02F44"/>
|
||||
<rect width="12" height="9.33333" fill="#46467F"/>
|
||||
<g filter="url(#filter0_d_503_3486)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.66665 1.99999C2.66665 2.36818 2.36817 2.66666 1.99998 2.66666C1.63179 2.66666 1.33331 2.36818 1.33331 1.99999C1.33331 1.63181 1.63179 1.33333 1.99998 1.33333C2.36817 1.33333 2.66665 1.63181 2.66665 1.99999ZM5.33331 1.99999C5.33331 2.36818 5.03484 2.66666 4.66665 2.66666C4.29846 2.66666 3.99998 2.36818 3.99998 1.99999C3.99998 1.63181 4.29846 1.33333 4.66665 1.33333C5.03484 1.33333 5.33331 1.63181 5.33331 1.99999ZM7.33331 2.66666C7.7015 2.66666 7.99998 2.36818 7.99998 1.99999C7.99998 1.63181 7.7015 1.33333 7.33331 1.33333C6.96512 1.33333 6.66665 1.63181 6.66665 1.99999C6.66665 2.36818 6.96512 2.66666 7.33331 2.66666ZM10.6666 1.99999C10.6666 2.36818 10.3682 2.66666 9.99998 2.66666C9.63179 2.66666 9.33331 2.36818 9.33331 1.99999C9.33331 1.63181 9.63179 1.33333 9.99998 1.33333C10.3682 1.33333 10.6666 1.63181 10.6666 1.99999ZM3.33331 3.99999C3.7015 3.99999 3.99998 3.70152 3.99998 3.33333C3.99998 2.96514 3.7015 2.66666 3.33331 2.66666C2.96512 2.66666 2.66665 2.96514 2.66665 3.33333C2.66665 3.70152 2.96512 3.99999 3.33331 3.99999ZM6.66665 3.33333C6.66665 3.70152 6.36817 3.99999 5.99998 3.99999C5.63179 3.99999 5.33331 3.70152 5.33331 3.33333C5.33331 2.96514 5.63179 2.66666 5.99998 2.66666C6.36817 2.66666 6.66665 2.96514 6.66665 3.33333ZM8.66665 3.99999C9.03484 3.99999 9.33331 3.70152 9.33331 3.33333C9.33331 2.96514 9.03484 2.66666 8.66665 2.66666C8.29846 2.66666 7.99998 2.96514 7.99998 3.33333C7.99998 3.70152 8.29846 3.99999 8.66665 3.99999ZM10.6666 4.66666C10.6666 5.03485 10.3682 5.33333 9.99998 5.33333C9.63179 5.33333 9.33331 5.03485 9.33331 4.66666C9.33331 4.29847 9.63179 3.99999 9.99998 3.99999C10.3682 3.99999 10.6666 4.29847 10.6666 4.66666ZM7.33331 5.33333C7.7015 5.33333 7.99998 5.03485 7.99998 4.66666C7.99998 4.29847 7.7015 3.99999 7.33331 3.99999C6.96512 3.99999 6.66665 4.29847 6.66665 4.66666C6.66665 5.03485 6.96512 5.33333 7.33331 5.33333ZM5.33331 4.66666C5.33331 5.03485 5.03484 5.33333 4.66665 5.33333C4.29846 5.33333 3.99998 5.03485 3.99998 4.66666C3.99998 4.29847 4.29846 3.99999 4.66665 3.99999C5.03484 3.99999 5.33331 4.29847 5.33331 4.66666ZM1.99998 5.33333C2.36817 5.33333 2.66665 5.03485 2.66665 4.66666C2.66665 4.29847 2.36817 3.99999 1.99998 3.99999C1.63179 3.99999 1.33331 4.29847 1.33331 4.66666C1.33331 5.03485 1.63179 5.33333 1.99998 5.33333ZM3.99998 5.99999C3.99998 6.36819 3.7015 6.66666 3.33331 6.66666C2.96512 6.66666 2.66665 6.36819 2.66665 5.99999C2.66665 5.6318 2.96512 5.33333 3.33331 5.33333C3.7015 5.33333 3.99998 5.6318 3.99998 5.99999ZM5.99998 6.66666C6.36817 6.66666 6.66665 6.36819 6.66665 5.99999C6.66665 5.6318 6.36817 5.33333 5.99998 5.33333C5.63179 5.33333 5.33331 5.6318 5.33331 5.99999C5.33331 6.36819 5.63179 6.66666 5.99998 6.66666ZM9.33331 5.99999C9.33331 6.36819 9.03484 6.66666 8.66665 6.66666C8.29846 6.66666 7.99998 6.36819 7.99998 5.99999C7.99998 5.6318 8.29846 5.33333 8.66665 5.33333C9.03484 5.33333 9.33331 5.6318 9.33331 5.99999ZM9.99998 8C10.3682 8 10.6666 7.70152 10.6666 7.33333C10.6666 6.96514 10.3682 6.66666 9.99998 6.66666C9.63179 6.66666 9.33331 6.96514 9.33331 7.33333C9.33331 7.70152 9.63179 8 9.99998 8ZM7.99998 7.33333C7.99998 7.70152 7.7015 8 7.33331 8C6.96512 8 6.66665 7.70152 6.66665 7.33333C6.66665 6.96514 6.96512 6.66666 7.33331 6.66666C7.7015 6.66666 7.99998 6.96514 7.99998 7.33333ZM4.66665 8C5.03484 8 5.33331 7.70152 5.33331 7.33333C5.33331 6.96514 5.03484 6.66666 4.66665 6.66666C4.29846 6.66666 3.99998 6.96514 3.99998 7.33333C3.99998 7.70152 4.29846 8 4.66665 8ZM2.66665 7.33333C2.66665 7.70152 2.36817 8 1.99998 8C1.63179 8 1.33331 7.70152 1.33331 7.33333C1.33331 6.96514 1.63179 6.66666 1.99998 6.66666C2.36817 6.66666 2.66665 6.96514 2.66665 7.33333Z" fill="url(#paint0_linear_503_3486)"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_503_3486" x="1.33331" y="1.33333" width="9.33331" height="7.66667" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.06 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_503_3486"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_503_3486" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_503_3486" x1="1.33331" y1="1.33333" x2="1.33331" y2="7.99999" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#F0F0F0"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_503_3486">
|
||||
<rect width="28" height="20" rx="2" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 648 B After Width: | Height: | Size: 5.5 KiB |
3
devtools_options.yaml
Normal file
3
devtools_options.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
@ -1,5 +1,5 @@
|
||||
arb-dir: l10n
|
||||
template-arb-file: app_ru.arb
|
||||
template-arb-file: app_en.arb
|
||||
output-localization: app_locale.dart
|
||||
output-dir: lib/components/locale/l10n
|
||||
output-class: AppLocale
|
||||
|
@ -1,21 +1,15 @@
|
||||
{
|
||||
"@@locale": "en",
|
||||
|
||||
"appBarTitle": "Harry Potter characters",
|
||||
"mainAppBarTitle": "Cryptocurrency Exchange",
|
||||
"detailsPageAppBarTitle": "Cryptocurrency info",
|
||||
"settingsPageAppBarTitle": "Settings",
|
||||
|
||||
"search": "Search",
|
||||
"liked": "You liked",
|
||||
"unliked": "Like removed from",
|
||||
"errorOccurred": "Error occurred",
|
||||
"noErrorMsg": "No message provided",
|
||||
"retry": "Retry",
|
||||
"unknown": "Unknown",
|
||||
"searchHint": "Search",
|
||||
"addedToFavourite": "is added to favourites",
|
||||
"removedFromFavourite": "is removed from favourites",
|
||||
|
||||
"apiYear": "Year",
|
||||
"apiType": "Type",
|
||||
"apiRating": "Rating",
|
||||
"apiDesc": "",
|
||||
"apiNoDesc": "No description provided",
|
||||
"coinDataPriceChange": "for the last 24 hours",
|
||||
|
||||
"arbEnding": "t"
|
||||
"settingsLanguage": "Language"
|
||||
}
|
@ -1,21 +1,15 @@
|
||||
{
|
||||
"@@locale": "ru",
|
||||
|
||||
"appBarTitle": "Персонажи из Гарри Поттера",
|
||||
"mainAppBarTitle": "Криптобиржа",
|
||||
"detailsPageAppBarTitle": "Сведения о валюте",
|
||||
"settingsPageAppBarTitle": "Настройки",
|
||||
|
||||
"search": "Поиск",
|
||||
"liked": "Вы добавили в избранное",
|
||||
"unliked": "Вы удалили из избранного",
|
||||
"errorOccured": "Произошла ошибка",
|
||||
"noErrorMsg": "Нет сообщения",
|
||||
"retry": "Повторить",
|
||||
"unknown": "Неизвестно",
|
||||
"searchHint": "Поиск",
|
||||
"addedToFavourite": "добавлен в избранное",
|
||||
"removedFromFavourite": "удален из избранного",
|
||||
|
||||
"apiYear": "Год",
|
||||
"apiType": "Тип",
|
||||
"apiRating": "Рейтинг",
|
||||
"apiDesc": "(Описание доступно только на английском языке)",
|
||||
"apiNoDesc": "Нет описания",
|
||||
"coinDataPriceChange": "за последние 24 часа",
|
||||
|
||||
"arbEnding": "t"
|
||||
"settingsLanguage": "Язык"
|
||||
}
|
@ -95,89 +95,53 @@ abstract class AppLocale {
|
||||
Locale('ru')
|
||||
];
|
||||
|
||||
/// No description provided for @appBarTitle.
|
||||
/// No description provided for @mainAppBarTitle.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Персонажи из Гарри Поттера'**
|
||||
String get appBarTitle;
|
||||
/// In en, this message translates to:
|
||||
/// **'Cryptocurrency Exchange'**
|
||||
String get mainAppBarTitle;
|
||||
|
||||
/// No description provided for @search.
|
||||
/// No description provided for @detailsPageAppBarTitle.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Поиск'**
|
||||
String get search;
|
||||
/// In en, this message translates to:
|
||||
/// **'Cryptocurrency info'**
|
||||
String get detailsPageAppBarTitle;
|
||||
|
||||
/// No description provided for @liked.
|
||||
/// No description provided for @settingsPageAppBarTitle.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Вы добавили в избранное'**
|
||||
String get liked;
|
||||
/// In en, this message translates to:
|
||||
/// **'Settings'**
|
||||
String get settingsPageAppBarTitle;
|
||||
|
||||
/// No description provided for @unliked.
|
||||
/// No description provided for @searchHint.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Вы удалили из избранного'**
|
||||
String get unliked;
|
||||
/// In en, this message translates to:
|
||||
/// **'Search'**
|
||||
String get searchHint;
|
||||
|
||||
/// No description provided for @errorOccured.
|
||||
/// No description provided for @addedToFavourite.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Произошла ошибка'**
|
||||
String get errorOccured;
|
||||
/// In en, this message translates to:
|
||||
/// **'is added to favourites'**
|
||||
String get addedToFavourite;
|
||||
|
||||
/// No description provided for @noErrorMsg.
|
||||
/// No description provided for @removedFromFavourite.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Нет сообщения'**
|
||||
String get noErrorMsg;
|
||||
/// In en, this message translates to:
|
||||
/// **'is removed from favourites'**
|
||||
String get removedFromFavourite;
|
||||
|
||||
/// No description provided for @retry.
|
||||
/// No description provided for @coinDataPriceChange.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Повторить'**
|
||||
String get retry;
|
||||
/// In en, this message translates to:
|
||||
/// **'for the last 24 hours'**
|
||||
String get coinDataPriceChange;
|
||||
|
||||
/// No description provided for @unknown.
|
||||
/// No description provided for @settingsLanguage.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Неизвестно'**
|
||||
String get unknown;
|
||||
|
||||
/// No description provided for @apiYear.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Год'**
|
||||
String get apiYear;
|
||||
|
||||
/// No description provided for @apiType.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Тип'**
|
||||
String get apiType;
|
||||
|
||||
/// No description provided for @apiRating.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Рейтинг'**
|
||||
String get apiRating;
|
||||
|
||||
/// No description provided for @apiDesc.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'(Описание доступно только на английском языке)'**
|
||||
String get apiDesc;
|
||||
|
||||
/// No description provided for @apiNoDesc.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'Нет описания'**
|
||||
String get apiNoDesc;
|
||||
|
||||
/// No description provided for @arbEnding.
|
||||
///
|
||||
/// In ru, this message translates to:
|
||||
/// **'t'**
|
||||
String get arbEnding;
|
||||
/// In en, this message translates to:
|
||||
/// **'Language'**
|
||||
String get settingsLanguage;
|
||||
}
|
||||
|
||||
class _AppLocaleDelegate extends LocalizationsDelegate<AppLocale> {
|
||||
|
@ -7,44 +7,26 @@ class AppLocaleEn extends AppLocale {
|
||||
AppLocaleEn([String locale = 'en']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appBarTitle => 'Harry Potter characters';
|
||||
String get mainAppBarTitle => 'Cryptocurrency Exchange';
|
||||
|
||||
@override
|
||||
String get search => 'Search';
|
||||
String get detailsPageAppBarTitle => 'Cryptocurrency info';
|
||||
|
||||
@override
|
||||
String get liked => 'You liked';
|
||||
String get settingsPageAppBarTitle => 'Settings';
|
||||
|
||||
@override
|
||||
String get unliked => 'Like removed from';
|
||||
String get searchHint => 'Search';
|
||||
|
||||
@override
|
||||
String get errorOccured => 'Произошла ошибка';
|
||||
String get addedToFavourite => 'is added to favourites';
|
||||
|
||||
@override
|
||||
String get noErrorMsg => 'No message provided';
|
||||
String get removedFromFavourite => 'is removed from favourites';
|
||||
|
||||
@override
|
||||
String get retry => 'Retry';
|
||||
String get coinDataPriceChange => 'for the last 24 hours';
|
||||
|
||||
@override
|
||||
String get unknown => 'Unknown';
|
||||
|
||||
@override
|
||||
String get apiYear => 'Year';
|
||||
|
||||
@override
|
||||
String get apiType => 'Type';
|
||||
|
||||
@override
|
||||
String get apiRating => 'Rating';
|
||||
|
||||
@override
|
||||
String get apiDesc => '';
|
||||
|
||||
@override
|
||||
String get apiNoDesc => 'No description provided';
|
||||
|
||||
@override
|
||||
String get arbEnding => 't';
|
||||
String get settingsLanguage => 'Language';
|
||||
}
|
||||
|
@ -7,44 +7,26 @@ class AppLocaleRu extends AppLocale {
|
||||
AppLocaleRu([String locale = 'ru']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appBarTitle => 'Персонажи из Гарри Поттера';
|
||||
String get mainAppBarTitle => 'Криптобиржа';
|
||||
|
||||
@override
|
||||
String get search => 'Поиск';
|
||||
String get detailsPageAppBarTitle => 'Сведения о валюте';
|
||||
|
||||
@override
|
||||
String get liked => 'Вы добавили в избранное';
|
||||
String get settingsPageAppBarTitle => 'Настройки';
|
||||
|
||||
@override
|
||||
String get unliked => 'Вы удалили из избранного';
|
||||
String get searchHint => 'Поиск';
|
||||
|
||||
@override
|
||||
String get errorOccured => 'Произошла ошибка';
|
||||
String get addedToFavourite => 'добавлен в избранное';
|
||||
|
||||
@override
|
||||
String get noErrorMsg => 'Нет сообщения';
|
||||
String get removedFromFavourite => 'удален из избранного';
|
||||
|
||||
@override
|
||||
String get retry => 'Повторить';
|
||||
String get coinDataPriceChange => 'за последние 24 часа';
|
||||
|
||||
@override
|
||||
String get unknown => 'Неизвестно';
|
||||
|
||||
@override
|
||||
String get apiYear => 'Год';
|
||||
|
||||
@override
|
||||
String get apiType => 'Тип';
|
||||
|
||||
@override
|
||||
String get apiRating => 'Рейтинг';
|
||||
|
||||
@override
|
||||
String get apiDesc => '(Описание доступно только на английском языке)';
|
||||
|
||||
@override
|
||||
String get apiNoDesc => 'Нет описания';
|
||||
|
||||
@override
|
||||
String get arbEnding => 't';
|
||||
String get settingsLanguage => 'Язык';
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'characters_dto.g.dart';
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class CharactersDto {
|
||||
final List<CharacterDataDto>? data;
|
||||
final MetaDto? meta;
|
||||
|
||||
const CharactersDto({this.data, this.meta});
|
||||
|
||||
factory CharactersDto.fromJson(Map<String, dynamic> json) => _$CharactersDtoFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class CharacterDataDto {
|
||||
final String? id;
|
||||
final String? type;
|
||||
final CharacterAttributesDataDto? attributes;
|
||||
|
||||
const CharacterDataDto({this.id, this.type, this.attributes});
|
||||
|
||||
factory CharacterDataDto.fromJson(Map<String, dynamic> json) => _$CharacterDataDtoFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class CharacterAttributesDataDto {
|
||||
final String? name;
|
||||
final String? born;
|
||||
final String? died;
|
||||
final String? image;
|
||||
|
||||
const CharacterAttributesDataDto({this.name, this.born, this.died, this.image});
|
||||
|
||||
factory CharacterAttributesDataDto.fromJson(Map<String, dynamic> json) => _$CharacterAttributesDataDtoFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class MetaDto {
|
||||
final PaginationDto? pagination;
|
||||
|
||||
const MetaDto({this.pagination});
|
||||
|
||||
factory MetaDto.fromJson(Map<String, dynamic> json) => _$MetaDtoFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class PaginationDto {
|
||||
final int? current;
|
||||
final int? next;
|
||||
final int? last;
|
||||
|
||||
const PaginationDto({this.current, this.next, this.last});
|
||||
|
||||
factory PaginationDto.fromJson(Map<String, dynamic> json) => _$PaginationDtoFromJson(json);
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'characters_dto.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
CharactersDto _$CharactersDtoFromJson(Map<String, dynamic> json) =>
|
||||
CharactersDto(
|
||||
data: (json['data'] as List<dynamic>?)
|
||||
?.map((e) => CharacterDataDto.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
meta: json['meta'] == null
|
||||
? null
|
||||
: MetaDto.fromJson(json['meta'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
CharacterDataDto _$CharacterDataDtoFromJson(Map<String, dynamic> json) =>
|
||||
CharacterDataDto(
|
||||
id: json['id'] as String?,
|
||||
type: json['type'] as String?,
|
||||
attributes: json['attributes'] == null
|
||||
? null
|
||||
: CharacterAttributesDataDto.fromJson(
|
||||
json['attributes'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
CharacterAttributesDataDto _$CharacterAttributesDataDtoFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
CharacterAttributesDataDto(
|
||||
name: json['name'] as String?,
|
||||
born: json['born'] as String?,
|
||||
died: json['died'] as String?,
|
||||
image: json['image'] as String?,
|
||||
);
|
||||
|
||||
MetaDto _$MetaDtoFromJson(Map<String, dynamic> json) => MetaDto(
|
||||
pagination: json['pagination'] == null
|
||||
? null
|
||||
: PaginationDto.fromJson(json['pagination'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
PaginationDto _$PaginationDtoFromJson(Map<String, dynamic> json) =>
|
||||
PaginationDto(
|
||||
current: (json['current'] as num?)?.toInt(),
|
||||
next: (json['next'] as num?)?.toInt(),
|
||||
last: (json['last'] as num?)?.toInt(),
|
||||
);
|
@ -2,13 +2,14 @@ import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'coins_dto.g.dart';
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class CoinsDto {
|
||||
final List<CoinDataDto>? coins;
|
||||
|
||||
CoinsDto({this.coins});
|
||||
|
||||
factory CoinsDto.fromJson(Map<String, dynamic> json) => _$CoinsDtoFromJson(json);
|
||||
factory CoinsDto.fromJson(List<dynamic> json) => CoinsDto(
|
||||
coins: json.map((e) => CoinDataDto.fromJson(e as Map<String, dynamic>)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
@ -16,7 +17,9 @@ class CoinDataDto {
|
||||
final String? id;
|
||||
final String? name;
|
||||
final String? image;
|
||||
@JsonKey(name: 'current_price')
|
||||
final double? currentPrice;
|
||||
@JsonKey(name: 'price_change_24h')
|
||||
final double? priceChange24h;
|
||||
|
||||
CoinDataDto({
|
||||
|
@ -6,16 +6,10 @@ part of 'coins_dto.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
CoinsDto _$CoinsDtoFromJson(Map<String, dynamic> json) => CoinsDto(
|
||||
coins: (json['coins'] as List<dynamic>?)
|
||||
?.map((e) => CoinDataDto.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
CoinDataDto _$CoinDataDtoFromJson(Map<String, dynamic> json) => CoinDataDto(
|
||||
id: json['id'] as String?,
|
||||
name: json['name'] as String?,
|
||||
image: json['image'] as String?,
|
||||
currentPrice: (json['currentPrice'] as num?)?.toDouble(),
|
||||
priceChange24h: (json['priceChange24h'] as num?)?.toDouble(),
|
||||
currentPrice: (json['current_price'] as num?)?.toDouble(),
|
||||
priceChange24h: (json['price_change_24h'] as num?)?.toDouble(),
|
||||
);
|
||||
|
@ -1,34 +0,0 @@
|
||||
import 'package:flutter_android_app/data/dtos/characters_dto.dart';
|
||||
import 'package:flutter_android_app/domain/models/card.dart';
|
||||
|
||||
import '../../domain/models/home.dart';
|
||||
|
||||
const _imagePlaceholder = 'https://gryazoveckij-r19.gosweb.gosuslugi.ru/netcat_files/460/2008/net_foto_muzh.jpg';
|
||||
|
||||
/*
|
||||
extension CharactersDataDto on CharactersDto {
|
||||
HomeData toDomain() => HomeData(
|
||||
data: data?.map((e) => e.toDomain()).toList(),
|
||||
nextPage: meta?.pagination?.next,
|
||||
);
|
||||
}
|
||||
|
||||
extension CharacterDataDtoToModel on CharacterDataDto {
|
||||
CardData toDomain() => CardData(
|
||||
title: attributes?.name ?? 'UNKNOWN',
|
||||
imageUrl: attributes?.image ?? _imagePlaceholder,
|
||||
description: _makeDescriptionText(attributes?.born, attributes?.died),
|
||||
id: id,
|
||||
);
|
||||
}
|
||||
|
||||
String _makeDescriptionText(String? born, String? died) {
|
||||
return born != null && died != null
|
||||
? '$born - $died'
|
||||
: born != null
|
||||
? 'born: $born'
|
||||
: died != null
|
||||
? 'died: $died'
|
||||
: '';
|
||||
}
|
||||
*/
|
@ -35,13 +35,13 @@ extension CoinDataDtoToModel on CoinDataDto {
|
||||
|
||||
retVal += _getLocalizedPrice(priceChange, locale?.localeName);
|
||||
|
||||
return '$retVal за последние 24 часа';
|
||||
return '$retVal ${locale?.coinDataPriceChange}';
|
||||
}
|
||||
}
|
||||
|
||||
extension CoinsDtoToModel on CoinsDto {
|
||||
HomeData toDomain(AppLocale? locale) => HomeData(
|
||||
HomeData toDomain(AppLocale? locale, int currentPage) => HomeData(
|
||||
data: coins?.map((e) => e.toDomain(locale)).toList(),
|
||||
nextPage: 1,
|
||||
nextPage: currentPage + 1,
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CardData {
|
||||
final String id;
|
||||
final String title;
|
||||
|
@ -1,12 +1,13 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_android_app/components/extensions/context_x.dart';
|
||||
import 'package:flutter_android_app/presentation/home_page/bloc/bloc.dart';
|
||||
import 'package:flutter_android_app/presentation/home_page/home_page.dart';
|
||||
import 'package:flutter_android_app/presentation/like_bloc/like_bloc.dart';
|
||||
import 'package:flutter_android_app/presentation/locale_bloc/locale_bloc.dart';
|
||||
import 'package:flutter_android_app/presentation/locale_bloc/locale_state.dart';
|
||||
import 'package:flutter_android_app/repositories/mock_repository.dart';
|
||||
import 'package:flutter_android_app/repositories/crypto_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'components/locale/l10n/app_localizations.dart';
|
||||
@ -25,7 +26,7 @@ class MyApp extends StatelessWidget {
|
||||
create: (context) => LikeBloc(),
|
||||
child: BlocProvider<LocaleBloc>(
|
||||
lazy: false,
|
||||
create: (context) => LocaleBloc(Locale(Platform.localeName)),
|
||||
create: (context) => LocaleBloc(Locale(_getLangCode(Platform.localeName))),
|
||||
child: BlocBuilder<LocaleBloc, LocaleState>(
|
||||
builder: (context, state) => MaterialApp(
|
||||
title: 'Cryptocurrency Exchange App',
|
||||
@ -37,13 +38,13 @@ class MyApp extends StatelessWidget {
|
||||
useMaterial3: true,
|
||||
),
|
||||
debugShowCheckedModeBanner: false,
|
||||
home: RepositoryProvider<MockRepository>(
|
||||
home: RepositoryProvider<CryptoRepository>(
|
||||
lazy: true,
|
||||
create: (_) => MockRepository(),
|
||||
create: (_) => CryptoRepository(),
|
||||
child: BlocProvider<HomeBloc>(
|
||||
lazy: false,
|
||||
create: (context) => HomeBloc(context.read<MockRepository>()),
|
||||
child: const MyHomePage(title: 'Cryptocurrency Exchange'),
|
||||
create: (context) => HomeBloc(context.read<CryptoRepository>()),
|
||||
child: const MyHomePage(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -51,4 +52,9 @@ class MyApp extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getLangCode(String fullLocaleName) {
|
||||
int index = fullLocaleName.indexOf('_');
|
||||
return index != -1 ? fullLocaleName.substring(0, index) : fullLocaleName;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_android_app/components/extensions/context_x.dart';
|
||||
import 'package:flutter_android_app/domain/models/card.dart';
|
||||
|
||||
class DetailsPage extends StatelessWidget {
|
||||
@ -9,7 +10,10 @@ class DetailsPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(),
|
||||
appBar: AppBar(
|
||||
title: Text(context.locale.detailsPageAppBarTitle),
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
),
|
||||
body: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
@ -23,6 +23,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||
search: event.search,
|
||||
page: event.nextPage ?? 1,
|
||||
onError: (e) => error = e,
|
||||
locale: event.locale,
|
||||
);
|
||||
|
||||
if (event.nextPage != null) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'package:flutter_android_app/components/locale/l10n/app_localizations.dart';
|
||||
|
||||
abstract class HomeEvent {
|
||||
const HomeEvent();
|
||||
}
|
||||
@ -5,6 +7,7 @@ abstract class HomeEvent {
|
||||
class HomeLoadDataEvent extends HomeEvent {
|
||||
final String? search;
|
||||
final int? nextPage;
|
||||
final AppLocale? locale;
|
||||
|
||||
const HomeLoadDataEvent({this.search, this.nextPage});
|
||||
const HomeLoadDataEvent({this.search, this.nextPage, this.locale});
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ class _Card extends StatelessWidget {
|
||||
final String? imageUrl;
|
||||
final String currentPrice;
|
||||
final String priceChange;
|
||||
final AppLocale locale;
|
||||
final OnLikeCallback onLike;
|
||||
final VoidCallback? onTap;
|
||||
final bool isLiked;
|
||||
@ -20,14 +19,12 @@ class _Card extends StatelessWidget {
|
||||
this.imageUrl,
|
||||
required this.currentPrice,
|
||||
required this.priceChange,
|
||||
required this.locale,
|
||||
this.onLike,
|
||||
this.onTap,
|
||||
this.isLiked = false,
|
||||
});
|
||||
|
||||
factory _Card.fromData(
|
||||
AppLocale locale,
|
||||
CardData data, {
|
||||
OnLikeCallback onLike,
|
||||
VoidCallback? onTap,
|
||||
@ -38,7 +35,6 @@ class _Card extends StatelessWidget {
|
||||
imageUrl: data.imageUrl,
|
||||
currentPrice: data.currentPrice,
|
||||
priceChange: data.priceChange,
|
||||
locale: locale,
|
||||
onLike: onLike,
|
||||
onTap: onTap,
|
||||
isLiked: isLiked,
|
||||
|
@ -1,7 +1,5 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_android_app/components/extensions/context_x.dart';
|
||||
import 'package:flutter_android_app/components/locale/l10n/app_localizations.dart';
|
||||
import 'package:flutter_android_app/components/utils/debounce.dart';
|
||||
import 'package:flutter_android_app/domain/models/card.dart';
|
||||
import 'package:flutter_android_app/presentation/details_page/details_page.dart';
|
||||
@ -14,24 +12,19 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../common/svg_objects.dart';
|
||||
import '../like_bloc/like_events.dart';
|
||||
import '../locale_bloc/locale_bloc.dart';
|
||||
import '../locale_bloc/locale_events.dart';
|
||||
import '../locale_bloc/locale_state.dart';
|
||||
import '../settings_page/settings_page.dart';
|
||||
|
||||
part 'card.dart';
|
||||
|
||||
class MyHomePage extends StatelessWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
|
||||
final String title;
|
||||
const MyHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: Text(title),
|
||||
title: Text(context.locale.mainAppBarTitle),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 12.0),
|
||||
@ -43,7 +36,6 @@ class MyHomePage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
),
|
||||
body: const Body(),
|
||||
);
|
||||
@ -66,7 +58,7 @@ class _BodyState extends State<Body> {
|
||||
SvgObjects.init();
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.read<HomeBloc>().add(const HomeLoadDataEvent());
|
||||
context.read<HomeBloc>().add(HomeLoadDataEvent(locale: context.locale));
|
||||
context.read<LikeBloc>().add(const LoadLikesEvent());
|
||||
});
|
||||
|
||||
@ -90,23 +82,25 @@ class _BodyState extends State<Body> {
|
||||
child: SearchBar(
|
||||
controller: searchController,
|
||||
onChanged: (search) {
|
||||
Debounce.run(() => context.read<HomeBloc>().add(HomeLoadDataEvent(search: search)));
|
||||
Debounce.run(() => context.read<HomeBloc>().add(HomeLoadDataEvent(search: search, locale: context.locale)));
|
||||
},
|
||||
leading: const Icon(Icons.search),
|
||||
trailing: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () { searchController.clear(); },
|
||||
onPressed: () {
|
||||
searchController.clear();
|
||||
context.read<HomeBloc>().add(HomeLoadDataEvent(locale: context.locale));
|
||||
},
|
||||
),
|
||||
],
|
||||
hintText: context.locale.search,
|
||||
hintText: context.locale.searchHint,
|
||||
elevation: const WidgetStatePropertyAll(0.0),
|
||||
padding: const WidgetStatePropertyAll(EdgeInsets.only(left: 18, right: 10)),
|
||||
backgroundColor: WidgetStatePropertyAll(Theme.of(context).colorScheme.secondaryContainer),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
BlocBuilder<HomeBloc, HomeState>(
|
||||
@ -129,7 +123,6 @@ class _BodyState extends State<Body> {
|
||||
final data = state.data?.data?[index];
|
||||
return data != null
|
||||
? _Card.fromData(
|
||||
context.locale,
|
||||
data,
|
||||
isLiked: likeState.likedIds?.contains(data.id) == true,
|
||||
onLike: _onLike,
|
||||
@ -164,7 +157,7 @@ class _BodyState extends State<Body> {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text(
|
||||
'$title ${isLiked ? context.locale.liked : context.locale.unliked}',
|
||||
'$title ${isLiked ? context.locale.addedToFavourite : context.locale.removedFromFavourite}',
|
||||
style: Theme.of(context).textTheme.bodyLarge
|
||||
),
|
||||
backgroundColor: Colors.deepPurple.shade200,
|
||||
@ -174,11 +167,13 @@ class _BodyState extends State<Body> {
|
||||
}
|
||||
|
||||
void _navToDetails(BuildContext context, CardData data) {
|
||||
Navigator.push(context, CupertinoPageRoute(builder: (context) => DetailsPage(data)));
|
||||
Navigator.push(context, MaterialPageRoute<void>(
|
||||
builder: (context) => DetailsPage(data)),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onRefresh() {
|
||||
context.read<HomeBloc>().add(HomeLoadDataEvent(search: searchController.text));
|
||||
context.read<HomeBloc>().add(HomeLoadDataEvent(search: searchController.text, locale: context.locale));
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
@ -189,6 +184,7 @@ class _BodyState extends State<Body> {
|
||||
bloc.add(HomeLoadDataEvent(
|
||||
search: searchController.text,
|
||||
nextPage: bloc.state.data?.nextPage,
|
||||
locale: context.locale,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_android_app/components/extensions/context_x.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../common/svg_objects.dart';
|
||||
@ -12,14 +13,27 @@ class SettingsPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Settings')),
|
||||
body: Center(
|
||||
child: GestureDetector(
|
||||
appBar: AppBar(
|
||||
title: Text(context.locale.settingsPageAppBarTitle),
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(left: 20, right: 16, top: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'${context.locale.settingsLanguage}:',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => context.read<LocaleBloc>().add(const ChangeLocaleEvent()),
|
||||
child: SizedBox.square(
|
||||
dimension: 50,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 12),
|
||||
padding: const EdgeInsets.only(right: 0),
|
||||
child: BlocBuilder<LocaleBloc, LocaleState>(
|
||||
builder: (context, state) {
|
||||
return state.currentLocale.languageCode == 'ru'
|
||||
@ -29,6 +43,10 @@ class SettingsPage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -32,12 +32,13 @@ class CryptoRepository extends ApiInterface {
|
||||
}) async {
|
||||
try {
|
||||
Map<String, dynamic> queryParams = {
|
||||
'x_cg_demo_api_key': _apiKey,
|
||||
'vs_currency': _getCurrencyName(locale?.localeName),
|
||||
'per_page': pageSize,
|
||||
'page': page,
|
||||
};
|
||||
|
||||
if (search != null) {
|
||||
if (search != null && search.isNotEmpty) {
|
||||
final Response<dynamic> searchResponse = await _dio.get<Map<dynamic, dynamic>>(
|
||||
'$_baseUrl$_searchUrl',
|
||||
queryParameters: {
|
||||
@ -52,17 +53,22 @@ class CryptoRepository extends ApiInterface {
|
||||
for (var coinData in searchCoinsDto.coins!) {
|
||||
ids += coinData.id != null ? '${coinData.id},' : '';
|
||||
}
|
||||
|
||||
if (ids.isEmpty) {
|
||||
return HomeData();
|
||||
}
|
||||
|
||||
queryParams['ids'] = ids;
|
||||
}
|
||||
}
|
||||
|
||||
final Response<dynamic> response = await _dio.get<Map<dynamic, dynamic>>(
|
||||
final response = await _dio.get(
|
||||
'$_baseUrl$_coinsDataUrl',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
final CoinsDto dto = CoinsDto.fromJson(response.data as Map<String, dynamic>);
|
||||
final HomeData data = dto.toDomain(locale);
|
||||
final CoinsDto dto = CoinsDto.fromJson(response.data as List<dynamic>);
|
||||
final HomeData data = dto.toDomain(locale, page);
|
||||
return data;
|
||||
|
||||
} on DioException catch (e) {
|
||||
|
@ -1,46 +0,0 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter_android_app/data/dtos/characters_dto.dart';
|
||||
import 'package:flutter_android_app/data/mappers/characters_mapper.dart';
|
||||
import 'package:flutter_android_app/domain/models/home.dart';
|
||||
import 'package:flutter_android_app/repositories/api_interface.dart';
|
||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||
|
||||
import '../components/utils/error_callback.dart';
|
||||
/*
|
||||
class PotterRepository extends ApiInterface {
|
||||
static final Dio _dio = Dio()
|
||||
..interceptors.add(PrettyDioLogger(
|
||||
requestHeader: true,
|
||||
requestBody: true,
|
||||
));
|
||||
|
||||
static const String _baseUrl = 'https://api.potterdb.com';
|
||||
|
||||
@override
|
||||
Future<HomeData?> loadData({
|
||||
OnErrorCallback? onError,
|
||||
String? q, int page = 1,
|
||||
int pageSize = 20,
|
||||
}) async {
|
||||
try {
|
||||
const String url = '$_baseUrl/v1/characters';
|
||||
|
||||
final Response<dynamic> response = await _dio.get<Map<dynamic, dynamic>>(
|
||||
url,
|
||||
queryParameters: {
|
||||
'filter[name_cont]': q,
|
||||
'page[number]': page,
|
||||
'page[size]': pageSize,
|
||||
},
|
||||
);
|
||||
|
||||
final CharactersDto dto = CharactersDto.fromJson(response.data as Map<String, dynamic>);
|
||||
final HomeData data = dto.toDomain();
|
||||
return data;
|
||||
} on DioException catch (e) {
|
||||
onError?.call(e.error?.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
Loading…
Reference in New Issue
Block a user