ура пагинация работает теперь!!
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@mipmap/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
|
||||||
|
</adaptive-icon>
|
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 857 B |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 463 B |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 26 KiB |
BIN
assets/launcher.jpeg
Normal file
After Width: | Height: | Size: 29 KiB |
19
assets/svg/ru.svg
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?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>
|
After Width: | Height: | Size: 968 B |
23
assets/svg/uk.svg
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
viewBox="0 0 512 512" xml:space="preserve">
|
||||||
|
<path style="fill:#41479B;" d="M473.655,88.276H38.345C17.167,88.276,0,105.443,0,126.621V385.38
|
||||||
|
c0,21.177,17.167,38.345,38.345,38.345h435.31c21.177,0,38.345-17.167,38.345-38.345V126.621
|
||||||
|
C512,105.443,494.833,88.276,473.655,88.276z"/>
|
||||||
|
<path style="fill:#F5F5F5;" d="M511.469,120.282c-3.022-18.159-18.797-32.007-37.814-32.007h-9.977l-163.54,107.147V88.276h-88.276
|
||||||
|
v107.147L48.322,88.276h-9.977c-19.017,0-34.792,13.847-37.814,32.007l139.778,91.58H0v88.276h140.309L0.531,391.717
|
||||||
|
c3.022,18.159,18.797,32.007,37.814,32.007h9.977l163.54-107.147v107.147h88.276V316.577l163.54,107.147h9.977
|
||||||
|
c19.017,0,34.792-13.847,37.814-32.007l-139.778-91.58H512v-88.276H371.691L511.469,120.282z"/>
|
||||||
|
<g>
|
||||||
|
<polygon style="fill:#FF4B55;" points="282.483,88.276 229.517,88.276 229.517,229.517 0,229.517 0,282.483 229.517,282.483
|
||||||
|
229.517,423.724 282.483,423.724 282.483,282.483 512,282.483 512,229.517 282.483,229.517 "/>
|
||||||
|
<path style="fill:#FF4B55;" d="M24.793,421.252l186.583-121.114h-32.428L9.224,410.31
|
||||||
|
C13.377,415.157,18.714,418.955,24.793,421.252z"/>
|
||||||
|
<path style="fill:#FF4B55;" d="M346.388,300.138H313.96l180.716,117.305c5.057-3.321,9.277-7.807,12.287-13.075L346.388,300.138z"
|
||||||
|
/>
|
||||||
|
<path style="fill:#FF4B55;" d="M4.049,109.475l157.73,102.387h32.428L15.475,95.842C10.676,99.414,6.749,104.084,4.049,109.475z"/>
|
||||||
|
<path style="fill:#FF4B55;" d="M332.566,211.862l170.035-110.375c-4.199-4.831-9.578-8.607-15.699-10.86L300.138,211.862H332.566z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
153
lib/components/locale/l10n/app_locale.dart
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
import 'package:intl/intl.dart' as intl;
|
||||||
|
|
||||||
|
import 'app_locale_en.dart';
|
||||||
|
import 'app_locale_ru.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
|
||||||
|
/// Callers can lookup localized strings with an instance of AppLocale
|
||||||
|
/// returned by `AppLocale.of(context)`.
|
||||||
|
///
|
||||||
|
/// Applications need to include `AppLocale.delegate()` in their app's
|
||||||
|
/// `localizationDelegates` list, and the locales they support in the app's
|
||||||
|
/// `supportedLocales` list. For example:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// import 'l10n/app_locale.dart';
|
||||||
|
///
|
||||||
|
/// return MaterialApp(
|
||||||
|
/// localizationsDelegates: AppLocale.localizationsDelegates,
|
||||||
|
/// supportedLocales: AppLocale.supportedLocales,
|
||||||
|
/// home: MyApplicationHome(),
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Update pubspec.yaml
|
||||||
|
///
|
||||||
|
/// Please make sure to update your pubspec.yaml to include the following
|
||||||
|
/// packages:
|
||||||
|
///
|
||||||
|
/// ```yaml
|
||||||
|
/// dependencies:
|
||||||
|
/// # Internationalization support.
|
||||||
|
/// flutter_localizations:
|
||||||
|
/// sdk: flutter
|
||||||
|
/// intl: any # Use the pinned version from flutter_localizations
|
||||||
|
///
|
||||||
|
/// # Rest of dependencies
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## iOS Applications
|
||||||
|
///
|
||||||
|
/// iOS applications define key application metadata, including supported
|
||||||
|
/// locales, in an Info.plist file that is built into the application bundle.
|
||||||
|
/// To configure the locales supported by your app, you’ll need to edit this
|
||||||
|
/// file.
|
||||||
|
///
|
||||||
|
/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file.
|
||||||
|
/// Then, in the Project Navigator, open the Info.plist file under the Runner
|
||||||
|
/// project’s Runner folder.
|
||||||
|
///
|
||||||
|
/// Next, select the Information Property List item, select Add Item from the
|
||||||
|
/// Editor menu, then select Localizations from the pop-up menu.
|
||||||
|
///
|
||||||
|
/// Select and expand the newly-created Localizations item then, for each
|
||||||
|
/// locale your application supports, add a new item and select the locale
|
||||||
|
/// you wish to add from the pop-up menu in the Value field. This list should
|
||||||
|
/// be consistent with the languages listed in the AppLocale.supportedLocales
|
||||||
|
/// property.
|
||||||
|
abstract class AppLocale {
|
||||||
|
AppLocale(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||||
|
|
||||||
|
final String localeName;
|
||||||
|
|
||||||
|
static AppLocale? of(BuildContext context) {
|
||||||
|
return Localizations.of<AppLocale>(context, AppLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const LocalizationsDelegate<AppLocale> delegate = _AppLocaleDelegate();
|
||||||
|
|
||||||
|
/// A list of this localizations delegate along with the default localizations
|
||||||
|
/// delegates.
|
||||||
|
///
|
||||||
|
/// Returns a list of localizations delegates containing this delegate along with
|
||||||
|
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
|
||||||
|
/// and GlobalWidgetsLocalizations.delegate.
|
||||||
|
///
|
||||||
|
/// Additional delegates can be added by appending to this list in
|
||||||
|
/// MaterialApp. This list does not have to be used at all if a custom list
|
||||||
|
/// of delegates is preferred or required.
|
||||||
|
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
|
||||||
|
delegate,
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
];
|
||||||
|
|
||||||
|
/// A list of this localizations delegate's supported locales.
|
||||||
|
static const List<Locale> supportedLocales = <Locale>[
|
||||||
|
Locale('en'),
|
||||||
|
Locale('ru')
|
||||||
|
];
|
||||||
|
|
||||||
|
/// No description provided for @search.
|
||||||
|
///
|
||||||
|
/// In ru, this message translates to:
|
||||||
|
/// **'Поиск'**
|
||||||
|
String get search;
|
||||||
|
|
||||||
|
/// No description provided for @liked.
|
||||||
|
///
|
||||||
|
/// In ru, this message translates to:
|
||||||
|
/// **'понравился!'**
|
||||||
|
String get liked;
|
||||||
|
|
||||||
|
/// No description provided for @disliked.
|
||||||
|
///
|
||||||
|
/// In ru, this message translates to:
|
||||||
|
/// **'разонравился :('**
|
||||||
|
String get disliked;
|
||||||
|
|
||||||
|
/// No description provided for @arbEnding.
|
||||||
|
///
|
||||||
|
/// In ru, this message translates to:
|
||||||
|
/// **'Чтобы не забыть про отсутствие запятой :)'**
|
||||||
|
String get arbEnding;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppLocaleDelegate extends LocalizationsDelegate<AppLocale> {
|
||||||
|
const _AppLocaleDelegate();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<AppLocale> load(Locale locale) {
|
||||||
|
return SynchronousFuture<AppLocale>(lookupAppLocale(locale));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isSupported(Locale locale) => <String>['en', 'ru'].contains(locale.languageCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldReload(_AppLocaleDelegate old) => false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppLocale lookupAppLocale(Locale locale) {
|
||||||
|
|
||||||
|
|
||||||
|
// Lookup logic when only language code is specified.
|
||||||
|
switch (locale.languageCode) {
|
||||||
|
case 'en': return AppLocaleEn();
|
||||||
|
case 'ru': return AppLocaleRu();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw FlutterError(
|
||||||
|
'AppLocale.delegate failed to load unsupported locale "$locale". This is likely '
|
||||||
|
'an issue with the localizations generation tool. Please file an issue '
|
||||||
|
'on GitHub with a reproducible sample app and the gen-l10n configuration '
|
||||||
|
'that was used.'
|
||||||
|
);
|
||||||
|
}
|
20
lib/components/locale/l10n/app_locale_en.dart
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import 'app_locale.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
|
||||||
|
/// The translations for English (`en`).
|
||||||
|
class AppLocaleEn extends AppLocale {
|
||||||
|
AppLocaleEn([String locale = 'en']) : super(locale);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get search => 'Search';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get liked => 'liked!';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get disliked => 'disliked :(';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)';
|
||||||
|
}
|
20
lib/components/locale/l10n/app_locale_ru.dart
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import 'app_locale.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
|
||||||
|
/// The translations for Russian (`ru`).
|
||||||
|
class AppLocaleRu extends AppLocale {
|
||||||
|
AppLocaleRu([String locale = 'ru']) : super(locale);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get search => 'Поиск';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get liked => 'Добавлено в понравившиеся :)';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get disliked => 'Удалено из понравившегося :(';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)';
|
||||||
|
}
|
12
lib/components/resources.g.dart
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/// Generate by [asset_generator](https://github.com/fluttercandies/flutter_asset_generator) library.
|
||||||
|
/// PLEASE DO NOT EDIT MANUALLY.
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
class R {
|
||||||
|
const R._();
|
||||||
|
|
||||||
|
/// ![preview](file://C:\Users\Admin\Desktop\5 semestr\pmu\assets\svg\ru.svg)
|
||||||
|
static const String ASSETS_SVG_RU_SVG = 'assets/svg/ru.svg';
|
||||||
|
|
||||||
|
/// ![preview](file://C:\Users\Admin\Desktop\5 semestr\pmu\assets\svg\uk.svg)
|
||||||
|
static const String ASSETS_SVG_UK_SVG = 'assets/svg/uk.svg';
|
||||||
|
}
|
@ -21,7 +21,7 @@ class PotterRepository extends ApiInterface {
|
|||||||
OnErrorCallback? onError,
|
OnErrorCallback? onError,
|
||||||
String? q,
|
String? q,
|
||||||
int page = 1,
|
int page = 1,
|
||||||
int pageSize = 5,
|
int pageSize = 10,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
const String url = '$_baseUrl/v1/characters';
|
const String url = '$_baseUrl/v1/characters';
|
||||||
|
@ -37,7 +37,7 @@ class _Card extends StatelessWidget {
|
|||||||
onLike: onLike,
|
onLike: onLike,
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
isLiked: isLiked,
|
isLiked: isLiked,
|
||||||
id: data.id,
|
id: data.id.toString()
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -62,7 +62,7 @@ class BodyState extends State<Body> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onNextPageListener() {
|
void _onNextPageListener() {
|
||||||
if (scrollController.offset > scrollController.position.maxScrollExtent) {
|
if (scrollController.offset >= scrollController.position.maxScrollExtent) {
|
||||||
final bloc = context.read<HomeBloc>();
|
final bloc = context.read<HomeBloc>();
|
||||||
if (!bloc.state.isPaginationLoading) {
|
if (!bloc.state.isPaginationLoading) {
|
||||||
bloc.add(HomeLoadDataEvent(
|
bloc.add(HomeLoadDataEvent(
|
||||||
@ -143,7 +143,7 @@ class BodyState extends State<Body> {
|
|||||||
? _Card.fromData(
|
? _Card.fromData(
|
||||||
data,
|
data,
|
||||||
onLike: _onLike,
|
onLike: _onLike,
|
||||||
isLiked: likeState.likedIds?.contains(data.id) == true,
|
isLiked: likeState.likedIds?.contains(data.id.toString()) == true,
|
||||||
onTap: () => _navToDetails(context, data),
|
onTap: () => _navToDetails(context, data),
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink();
|
: const SizedBox.shrink();
|
||||||
|
36
lib/presentation/like_bloc/like_bloc.dart
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import 'like_event.dart';
|
||||||
|
import 'like_state.dart';
|
||||||
|
|
||||||
|
const String _likedPrefsKey = 'liked';
|
||||||
|
|
||||||
|
class LikeBloc extends Bloc<LikeEvent, LikeState> {
|
||||||
|
LikeBloc() : super(const LikeState(likedIds: [])) {
|
||||||
|
on<ChangeLikeEvent>(_onChangeLike);
|
||||||
|
on<LoadLikesEvent>(_onLoadLikes);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onLoadLikes(LoadLikesEvent event, Emitter<LikeState> emit) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
final data = prefs.getStringList(_likedPrefsKey);
|
||||||
|
|
||||||
|
emit(state.copyWith(likedIds: data));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onChangeLike(ChangeLikeEvent event, Emitter<LikeState> emit) async {
|
||||||
|
final updatedList = List<String>.from(state.likedIds ?? []);
|
||||||
|
|
||||||
|
if (updatedList.contains(event.id)) {
|
||||||
|
updatedList.remove(event.id);
|
||||||
|
} else {
|
||||||
|
updatedList.add(event.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
prefs.setStringList(_likedPrefsKey, updatedList);
|
||||||
|
|
||||||
|
emit(state.copyWith(likedIds: updatedList));
|
||||||
|
}
|
||||||
|
}
|
13
lib/presentation/like_bloc/like_event.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
abstract class LikeEvent {
|
||||||
|
const LikeEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadLikesEvent extends LikeEvent {
|
||||||
|
const LoadLikesEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeLikeEvent extends LikeEvent {
|
||||||
|
final String id;
|
||||||
|
|
||||||
|
const ChangeLikeEvent(this.id);
|
||||||
|
}
|
14
lib/presentation/like_bloc/like_state.dart
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
part 'like_state.g.dart';
|
||||||
|
|
||||||
|
@CopyWith()
|
||||||
|
class LikeState extends Equatable {
|
||||||
|
final List<String>? likedIds;
|
||||||
|
|
||||||
|
const LikeState({required this.likedIds});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [likedIds];
|
||||||
|
}
|
56
lib/presentation/like_bloc/like_state.g.dart
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'like_state.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// CopyWithGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
abstract class _$LikeStateCWProxy {
|
||||||
|
LikeState likedIds(List<String>? likedIds);
|
||||||
|
|
||||||
|
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `LikeState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
|
||||||
|
///
|
||||||
|
/// Usage
|
||||||
|
/// ```dart
|
||||||
|
/// LikeState(...).copyWith(id: 12, name: "My name")
|
||||||
|
/// ````
|
||||||
|
LikeState call({
|
||||||
|
List<String>? likedIds,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfLikeState.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfLikeState.copyWith.fieldName(...)`
|
||||||
|
class _$LikeStateCWProxyImpl implements _$LikeStateCWProxy {
|
||||||
|
const _$LikeStateCWProxyImpl(this._value);
|
||||||
|
|
||||||
|
final LikeState _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
LikeState likedIds(List<String>? likedIds) => this(likedIds: likedIds);
|
||||||
|
|
||||||
|
@override
|
||||||
|
|
||||||
|
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `LikeState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
|
||||||
|
///
|
||||||
|
/// Usage
|
||||||
|
/// ```dart
|
||||||
|
/// LikeState(...).copyWith(id: 12, name: "My name")
|
||||||
|
/// ````
|
||||||
|
LikeState call({
|
||||||
|
Object? likedIds = const $CopyWithPlaceholder(),
|
||||||
|
}) {
|
||||||
|
return LikeState(
|
||||||
|
likedIds: likedIds == const $CopyWithPlaceholder()
|
||||||
|
? _value.likedIds
|
||||||
|
// ignore: cast_nullable_to_non_nullable
|
||||||
|
: likedIds as List<String>?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension $LikeStateCopyWith on LikeState {
|
||||||
|
/// Returns a callable class that can be used as follows: `instanceOfLikeState.copyWith(...)` or like so:`instanceOfLikeState.copyWith.fieldName(...)`.
|
||||||
|
// ignore: library_private_types_in_public_api
|
||||||
|
_$LikeStateCWProxy get copyWith => _$LikeStateCWProxyImpl(this);
|
||||||
|
}
|
17
lib/presentation/locale_bloc/locale_bloc.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:pmu/components/locale/l10n/app_locale.dart';
|
||||||
|
import 'package:pmu/presentation/locale_bloc/locale_events.dart';
|
||||||
|
import 'package:pmu/presentation/locale_bloc/locale_state.dart';
|
||||||
|
|
||||||
|
class LocaleBloc extends Bloc<LocaleEvent, LocaleState> {
|
||||||
|
LocaleBloc(Locale defaultLocale) : super(LocaleState(currentLocale: defaultLocale)) {
|
||||||
|
on<ChangeLocaleEvent>(_onChangeLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onChangeLocale(ChangeLocaleEvent event, Emitter<LocaleState> emit) async {
|
||||||
|
final toChange = AppLocale.supportedLocales
|
||||||
|
.firstWhere((e) => e.languageCode != state.currentLocale.languageCode);
|
||||||
|
emit(state.copyWith(currentLocale: toChange));
|
||||||
|
}
|
||||||
|
}
|
7
lib/presentation/locale_bloc/locale_events.dart
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
abstract class LocaleEvent {
|
||||||
|
const LocaleEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeLocaleEvent extends LocaleEvent {
|
||||||
|
const ChangeLocaleEvent();
|
||||||
|
}
|
15
lib/presentation/locale_bloc/locale_state.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
part 'locale_state.g.dart';
|
||||||
|
|
||||||
|
@CopyWith()
|
||||||
|
class LocaleState extends Equatable {
|
||||||
|
final Locale currentLocale;
|
||||||
|
|
||||||
|
const LocaleState({required this.currentLocale});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [currentLocale];
|
||||||
|
}
|
58
lib/presentation/locale_bloc/locale_state.g.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'locale_state.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// CopyWithGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
abstract class _$LocaleStateCWProxy {
|
||||||
|
LocaleState currentLocale(Locale currentLocale);
|
||||||
|
|
||||||
|
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `LocaleState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
|
||||||
|
///
|
||||||
|
/// Usage
|
||||||
|
/// ```dart
|
||||||
|
/// LocaleState(...).copyWith(id: 12, name: "My name")
|
||||||
|
/// ````
|
||||||
|
LocaleState call({
|
||||||
|
Locale? currentLocale,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfLocaleState.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfLocaleState.copyWith.fieldName(...)`
|
||||||
|
class _$LocaleStateCWProxyImpl implements _$LocaleStateCWProxy {
|
||||||
|
const _$LocaleStateCWProxyImpl(this._value);
|
||||||
|
|
||||||
|
final LocaleState _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
LocaleState currentLocale(Locale currentLocale) =>
|
||||||
|
this(currentLocale: currentLocale);
|
||||||
|
|
||||||
|
@override
|
||||||
|
|
||||||
|
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `LocaleState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
|
||||||
|
///
|
||||||
|
/// Usage
|
||||||
|
/// ```dart
|
||||||
|
/// LocaleState(...).copyWith(id: 12, name: "My name")
|
||||||
|
/// ````
|
||||||
|
LocaleState call({
|
||||||
|
Object? currentLocale = const $CopyWithPlaceholder(),
|
||||||
|
}) {
|
||||||
|
return LocaleState(
|
||||||
|
currentLocale:
|
||||||
|
currentLocale == const $CopyWithPlaceholder() || currentLocale == null
|
||||||
|
? _value.currentLocale
|
||||||
|
// ignore: cast_nullable_to_non_nullable
|
||||||
|
: currentLocale as Locale,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension $LocaleStateCopyWith on LocaleState {
|
||||||
|
/// Returns a callable class that can be used as follows: `instanceOfLocaleState.copyWith(...)` or like so:`instanceOfLocaleState.copyWith.fieldName(...)`.
|
||||||
|
// ignore: library_private_types_in_public_api
|
||||||
|
_$LocaleStateCWProxy get copyWith => _$LocaleStateCWProxyImpl(this);
|
||||||
|
}
|