локаль дописать осталось :)
This commit is contained in:
parent
f492991a36
commit
2d49ce9f8c
@ -1,9 +1,13 @@
|
|||||||
{
|
{
|
||||||
"@@locale": "en",
|
"@@locale": "en",
|
||||||
|
|
||||||
"search": "Search",
|
"title": "Quotes"
|
||||||
|
"search_word": "Search by word",
|
||||||
|
"search_author": "Search by author",
|
||||||
"liked": "Like :)",
|
"liked": "Like :)",
|
||||||
"disliked": "Dislike :(",
|
"disliked": "Dislike :(",
|
||||||
|
"error": "Error :C"
|
||||||
|
"details": "Details of quote"
|
||||||
|
|
||||||
"arbEnding": ""
|
"arbEnding": ""
|
||||||
}
|
}
|
@ -7,7 +7,7 @@ class AppLocaleEn extends AppLocale {
|
|||||||
AppLocaleEn([String locale = 'en']) : super(locale);
|
AppLocaleEn([String locale = 'en']) : super(locale);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get search => 'Search';
|
String get search => 'Поиск';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get liked => 'Like :)';
|
String get liked => 'Like :)';
|
||||||
|
@ -16,9 +16,10 @@ class QuoteDataDto {
|
|||||||
final String? body;
|
final String? body;
|
||||||
final String? author;
|
final String? author;
|
||||||
final String? imageUrl;
|
final String? imageUrl;
|
||||||
final String? id;
|
final dynamic id;
|
||||||
|
final bool? isLiked;
|
||||||
|
|
||||||
const QuoteDataDto({this.body, this.author, this.imageUrl, this.id});
|
const QuoteDataDto({this.body, this.author, this.imageUrl, this.id, this.isLiked});
|
||||||
|
|
||||||
factory QuoteDataDto.fromJson(Map<String, dynamic> json) => _$QuoteDataDtoFromJson(json);
|
factory QuoteDataDto.fromJson(Map<String, dynamic> json) => _$QuoteDataDtoFromJson(json);
|
||||||
}
|
}
|
||||||
|
@ -16,4 +16,6 @@ QuoteDataDto _$QuoteDataDtoFromJson(Map<String, dynamic> json) => QuoteDataDto(
|
|||||||
body: json['body'] as String?,
|
body: json['body'] as String?,
|
||||||
author: json['author'] as String?,
|
author: json['author'] as String?,
|
||||||
imageUrl: json['imageUrl'] as String?,
|
imageUrl: json['imageUrl'] as String?,
|
||||||
|
id: json['id'],
|
||||||
|
isLiked: json['isLiked'] as bool?,
|
||||||
);
|
);
|
||||||
|
@ -9,6 +9,7 @@ extension QuoteDtoToModel on QuoteDataDto {
|
|||||||
body ?? 'Без текста',
|
body ?? 'Без текста',
|
||||||
author ?? 'Неизвестный автор',
|
author ?? 'Неизвестный автор',
|
||||||
imageUrl ?? _imagePlaceholder,
|
imageUrl ?? _imagePlaceholder,
|
||||||
id ?? "",
|
id?.toString() ?? "",
|
||||||
|
isLiked ?? false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,6 @@ class Quote {
|
|||||||
final String author;
|
final String author;
|
||||||
final String imagePath;
|
final String imagePath;
|
||||||
final String id;
|
final String id;
|
||||||
bool isFavorite;
|
final bool isLiked;
|
||||||
|
Quote(this.text, this.author, this.imagePath, this.id, this.isLiked);
|
||||||
Quote(this.text, this.author, this.imagePath, this.id,[this.isFavorite = false]);
|
|
||||||
|
|
||||||
bool toggleFavorite() {
|
|
||||||
isFavorite = !isFavorite;
|
|
||||||
return isFavorite;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:pmu_flutter_labs/presentation/home_page/bloc/events.dart';
|
import 'package:pmu_flutter_labs/presentation/home_page/bloc/events.dart';
|
||||||
import 'package:pmu_flutter_labs/presentation/like_bloc/like_bloc.dart';
|
import 'package:pmu_flutter_labs/presentation/like_bloc/like_bloc.dart';
|
||||||
|
import 'package:pmu_flutter_labs/presentation/locale_bloc/locale_bloc.dart';
|
||||||
|
import 'package:pmu_flutter_labs/presentation/locale_bloc/locale_state.dart';
|
||||||
import 'components/locale/l10n/app_locale.dart';
|
import 'components/locale/l10n/app_locale.dart';
|
||||||
import 'data/repositories/quotes_repository.dart';
|
import 'data/repositories/quotes_repository.dart';
|
||||||
import '/presentation/home_page/bloc/bloc.dart';
|
import '/presentation/home_page/bloc/bloc.dart';
|
||||||
@ -15,8 +19,14 @@ class MyApp extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider<LocaleBloc>(
|
||||||
|
lazy: false,
|
||||||
|
create:(context) => LocaleBloc(Locale(Platform.localeName)),
|
||||||
|
child: BlocBuilder<LocaleBloc, LocaleState>(
|
||||||
|
builder: (context, state) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'Цитаты',
|
title: 'Цитаты',
|
||||||
|
locale: state.currentLocale,
|
||||||
localizationsDelegates: AppLocale.localizationsDelegates,
|
localizationsDelegates: AppLocale.localizationsDelegates,
|
||||||
supportedLocales: AppLocale.supportedLocales,
|
supportedLocales: AppLocale.supportedLocales,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
@ -26,16 +36,20 @@ class MyApp extends StatelessWidget {
|
|||||||
home: RepositoryProvider<QuotesRepository>(
|
home: RepositoryProvider<QuotesRepository>(
|
||||||
lazy: true,
|
lazy: true,
|
||||||
create: (_) => QuotesRepository(),
|
create: (_) => QuotesRepository(),
|
||||||
child: BlocProvider(
|
child: BlocProvider<LikeBloc>(
|
||||||
|
lazy: false,
|
||||||
create: (context) => LikeBloc(), // Add LikeBloc here
|
create: (context) => LikeBloc(), // Add LikeBloc here
|
||||||
child: BlocProvider(
|
child: BlocProvider<HomeBloc>(
|
||||||
create: (context) => HomeBloc(context.read<QuotesRepository>())
|
lazy: false,
|
||||||
..add(const HomeLoadDataEvent()), // Ensure initial load
|
create: (context) => HomeBloc(context.read<QuotesRepository>()),
|
||||||
child: const MyHomePage(title: "Цитаты"),
|
child: const MyHomePage(title: "Цитаты"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import '../../../domain/quote.dart';
|
|||||||
import '../home_page.dart';
|
import '../home_page.dart';
|
||||||
|
|
||||||
class HomeState extends Equatable {
|
class HomeState extends Equatable {
|
||||||
final Future<List<Quote>>? data; // Изменено
|
final Future<List<Quote>>? data;
|
||||||
|
|
||||||
const HomeState({this.data});
|
const HomeState({this.data});
|
||||||
|
|
||||||
|
@ -1,65 +1,63 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import '../../domain/quote.dart';
|
import '../../domain/quote.dart';
|
||||||
import '../like_bloc/like_bloc.dart';
|
|
||||||
import '../like_bloc/like_state.dart';
|
|
||||||
import 'home_page.dart';
|
import 'home_page.dart';
|
||||||
|
|
||||||
class QuoteCard extends StatelessWidget {
|
class QuoteCard extends StatelessWidget {
|
||||||
final Quote quote;
|
final Quote quote;
|
||||||
final VoidCallback onFavoriteToggle;
|
final VoidCallback onFavoriteToggle;
|
||||||
|
final bool isLiked;
|
||||||
|
|
||||||
const QuoteCard({Key? key, required this.quote, required this.onFavoriteToggle}) : super(key: key);
|
const QuoteCard({
|
||||||
|
super.key,
|
||||||
|
required this.quote,
|
||||||
|
required this.onFavoriteToggle,
|
||||||
|
required this.isLiked,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.all(8.0),
|
margin: const EdgeInsets.symmetric(
|
||||||
child: Padding(
|
vertical: 8.0,
|
||||||
padding: const EdgeInsets.all(16.0),
|
horizontal: 10.0,
|
||||||
child: Column(
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: ListTile(
|
||||||
children: [
|
contentPadding: const EdgeInsets.all(8.0),
|
||||||
Text(
|
leading: SizedBox(
|
||||||
|
width: 50.0,
|
||||||
|
child: Image.network(
|
||||||
|
quote.imagePath,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
errorBuilder: (_, __, ___) =>
|
||||||
|
const Icon(Icons.error, color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
quote.text,
|
quote.text,
|
||||||
style: const TextStyle(fontSize: 18.0),
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8.0),
|
subtitle: Text('- ${quote.author}'),
|
||||||
Text(
|
trailing: IconButton(
|
||||||
'- ${quote.author}',
|
icon: Icon(
|
||||||
style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 16.0),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8.0),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
ElevatedButton.icon(
|
|
||||||
onPressed: onFavoriteToggle,
|
|
||||||
icon: BlocBuilder<LikeBloc, LikeState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
final isLiked = state.likedIds?.contains(quote.id) ?? false;
|
|
||||||
return Icon(
|
|
||||||
isLiked ? Icons.favorite : Icons.favorite_border,
|
isLiked ? Icons.favorite : Icons.favorite_border,
|
||||||
color: isLiked ? Colors.red : Colors.grey,
|
color: isLiked ? Colors.red : null,
|
||||||
|
),
|
||||||
|
onPressed: onFavoriteToggle,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => QuoteDetailScreen(quote: quote),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
label: BlocBuilder<LikeBloc, LikeState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
final isLiked = state.likedIds?.contains(quote.id) ?? false;
|
|
||||||
return Text(isLiked ? 'Убрать из избранного' : 'Добавить в избранное');
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class QuoteDetailScreen extends StatelessWidget {
|
class QuoteDetailScreen extends StatelessWidget {
|
||||||
final Quote quote;
|
final Quote quote;
|
||||||
|
|
||||||
@ -80,7 +78,8 @@ class QuoteDetailScreen extends StatelessWidget {
|
|||||||
Image.network(
|
Image.network(
|
||||||
quote.imagePath,
|
quote.imagePath,
|
||||||
height: 150,
|
height: 150,
|
||||||
errorBuilder: (_, __, ___) => const Icon(Icons.error, color: Colors.red),
|
errorBuilder: (_, __, ___) =>
|
||||||
|
const Icon(Icons.error, color: Colors.red),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Text(
|
Text(
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:pmu_flutter_labs/components/extensions/context_x.dart';
|
import 'package:pmu_flutter_labs/components/extensions/context_x.dart';
|
||||||
|
import 'package:pmu_flutter_labs/presentation/like_bloc/like_state.dart';
|
||||||
import '../../components/utils/debounce.dart';
|
import '../../components/utils/debounce.dart';
|
||||||
import '../../domain/quote.dart';
|
import '../../domain/quote.dart';
|
||||||
import '../common/svg_objects.dart';
|
import '../common/svg_objects.dart';
|
||||||
import '../like_bloc/like_bloc.dart';
|
import '../like_bloc/like_bloc.dart';
|
||||||
import '../like_bloc/like_event.dart';
|
import '../like_bloc/like_event.dart';
|
||||||
|
import '../locale_bloc/locale_bloc.dart';
|
||||||
|
import '../locale_bloc/locale_events.dart';
|
||||||
|
import '../locale_bloc/locale_state.dart';
|
||||||
import '/data/repositories/quotes_repository.dart';
|
import '/data/repositories/quotes_repository.dart';
|
||||||
import '/presentation/home_page/bloc/bloc.dart';
|
import '/presentation/home_page/bloc/bloc.dart';
|
||||||
import '/presentation/home_page/bloc/events.dart';
|
import '/presentation/home_page/bloc/events.dart';
|
||||||
@ -17,15 +22,46 @@ class MyHomePage extends StatelessWidget {
|
|||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
|
get searchController => null;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => HomeBloc(QuotesRepository())..add(const HomeLoadDataEvent()),
|
create: (context) =>
|
||||||
|
HomeBloc(QuotesRepository())..add(const HomeLoadDataEvent()),
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(title),
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(title),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () =>
|
||||||
|
context.read<LocaleBloc>().add(const ChangeLocaleEvent()),
|
||||||
|
child: SizedBox.square(
|
||||||
|
dimension: 50,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 12),
|
||||||
|
child: BlocBuilder<LocaleBloc, LocaleState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return state.currentLocale.languageCode == 'ru'
|
||||||
|
? const SvgRu()
|
||||||
|
: const SvgUk();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: _HomePageBody(),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: const _HomePageBody(),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -64,8 +100,8 @@ class _HomePageBodyState extends State<_HomePageBody> {
|
|||||||
));
|
));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
context.read<HomeBloc>().add(const HomeLoadDataEvent());
|
||||||
context.read<LikeBloc>().add(const LoadLikesEvent());
|
context.read<LikeBloc>().add(const LoadLikesEvent());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showSnackbar(BuildContext context, bool isLiked) {
|
void _showSnackbar(BuildContext context, bool isLiked) {
|
||||||
@ -88,9 +124,9 @@ class _HomePageBodyState extends State<_HomePageBody> {
|
|||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: searchController,
|
controller: searchController,
|
||||||
decoration: const InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Поиск по цитате',
|
labelText: context.locale.search,
|
||||||
prefixIcon: Icon(Icons.search),
|
prefixIcon: const Icon(Icons.search),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -98,33 +134,43 @@ class _HomePageBodyState extends State<_HomePageBody> {
|
|||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: authorController,
|
controller: authorController,
|
||||||
decoration: const InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Поиск по автору',
|
labelText: context.locale.search,
|
||||||
prefixIcon: Icon(Icons.person),
|
prefixIcon: const Icon(Icons.person),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
BlocBuilder<LikeBloc, LikeState>(
|
||||||
|
builder: (context, likeState) {
|
||||||
|
return Expanded(
|
||||||
child: state.data == null
|
child: state.data == null
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
: FutureBuilder<List<Quote>?>(
|
: FutureBuilder<List<Quote>?>(
|
||||||
future: state.data,
|
future: state.data,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState ==
|
||||||
return const Center(child: CircularProgressIndicator());
|
ConnectionState.waiting) {
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return Center(child: Text('Ошибка: ${snapshot.error}'));
|
return Center(
|
||||||
|
child: Text('Ошибка: ${snapshot.error}'));
|
||||||
}
|
}
|
||||||
if (snapshot.data == null || snapshot.data!.isEmpty) {
|
if (snapshot.data == null ||
|
||||||
|
snapshot.data!.isEmpty) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Нет цитат для отображения.',
|
'Нет цитат для отображения.',
|
||||||
style: TextStyle(fontSize: 18, color: Colors.grey),
|
style: TextStyle(
|
||||||
|
fontSize: 18, color: Colors.grey),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final quotes = snapshot.data!;
|
final quotes = snapshot.data!;
|
||||||
|
final likedIds = likeState.likedIds ?? [];
|
||||||
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
context.read<HomeBloc>().add(HomeRefreshEvent(
|
context.read<HomeBloc>().add(HomeRefreshEvent(
|
||||||
@ -136,10 +182,15 @@ class _HomePageBodyState extends State<_HomePageBody> {
|
|||||||
itemCount: quotes.length,
|
itemCount: quotes.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final quote = quotes[index];
|
final quote = quotes[index];
|
||||||
|
final isLiked = likedIds.contains(quote.id);
|
||||||
|
|
||||||
return QuoteCard(
|
return QuoteCard(
|
||||||
quote: quote,
|
quote: quote,
|
||||||
|
isLiked: isLiked,
|
||||||
onFavoriteToggle: () {
|
onFavoriteToggle: () {
|
||||||
context.read<LikeBloc>().add(ChangeLikeEvent(quote.id));
|
context
|
||||||
|
.read<LikeBloc>()
|
||||||
|
.add(ChangeLikeEvent(quote.id));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -147,11 +198,12 @@ class _HomePageBodyState extends State<_HomePageBody> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
//import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
import 'like_event.dart';
|
import 'like_event.dart';
|
||||||
import 'like_state.dart';
|
import 'like_state.dart';
|
||||||
@ -13,10 +13,10 @@ class LikeBloc extends Bloc<LikeEvent, LikeState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onLoadLikes(LoadLikesEvent event, Emitter<LikeState> emit) async {
|
Future<void> _onLoadLikes(LoadLikesEvent event, Emitter<LikeState> emit) async {
|
||||||
//final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
//final data = prefs.getStringList(_likedPrefsKey);
|
final data = prefs.getStringList(_likedPrefsKey);
|
||||||
|
|
||||||
//emit(state.copyWith(likedIds: data));
|
emit(state.copyWith(likedIds: data));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onChangeLike(ChangeLikeEvent event, Emitter<LikeState> emit) async {
|
Future<void> _onChangeLike(ChangeLikeEvent event, Emitter<LikeState> emit) async {
|
||||||
@ -28,8 +28,8 @@ class LikeBloc extends Bloc<LikeEvent, LikeState> {
|
|||||||
updatedList.add(event.id);
|
updatedList.add(event.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
//final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
//prefs.setStringList(_likedPrefsKey, updatedList);
|
prefs.setStringList(_likedPrefsKey, updatedList);
|
||||||
|
|
||||||
emit(state.copyWith(likedIds: updatedList));
|
emit(state.copyWith(likedIds: updatedList));
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,5 @@ class LoadLikesEvent extends LikeEvent {
|
|||||||
|
|
||||||
class ChangeLikeEvent extends LikeEvent {
|
class ChangeLikeEvent extends LikeEvent {
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
const ChangeLikeEvent(this.id);
|
const ChangeLikeEvent(this.id);
|
||||||
}
|
}
|
17
lib/presentation/locale_bloc/locale_bloc.dart
Normal file
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 '../../components/locale/l10n/app_locale.dart';
|
||||||
|
import 'locale_events.dart';
|
||||||
|
import '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
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
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];
|
||||||
|
}
|
111
pubspec.lock
111
pubspec.lock
@ -325,6 +325,11 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_web_plugins:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
frontend_server_client:
|
frontend_server_client:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -533,6 +538,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
path_provider_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_linux
|
||||||
|
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
path_provider_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_platform_interface
|
||||||
|
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
path_provider_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_windows
|
||||||
|
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.0"
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -541,6 +570,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.2"
|
version: "6.0.2"
|
||||||
|
platform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: platform
|
||||||
|
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.6"
|
||||||
|
plugin_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: plugin_platform_interface
|
||||||
|
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.8"
|
||||||
pool:
|
pool:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -589,6 +634,62 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.0"
|
||||||
|
shared_preferences:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: shared_preferences
|
||||||
|
sha256: "3c7e73920c694a436afaf65ab60ce3453d91f84208d761fbd83fc21182134d93"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.4"
|
||||||
|
shared_preferences_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_android
|
||||||
|
sha256: "02a7d8a9ef346c9af715811b01fbd8e27845ad2c41148eefd31321471b41863d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.0"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_foundation
|
||||||
|
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.4"
|
||||||
|
shared_preferences_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_linux
|
||||||
|
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
shared_preferences_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_platform_interface
|
||||||
|
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
|
shared_preferences_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_web
|
||||||
|
sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
|
shared_preferences_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_windows
|
||||||
|
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.1"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -770,6 +871,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.1"
|
||||||
|
xdg_directories:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xdg_directories
|
||||||
|
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
xml:
|
xml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -788,4 +897,4 @@ packages:
|
|||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.5.4 <4.0.0"
|
dart: ">=3.5.4 <4.0.0"
|
||||||
flutter: ">=3.22.0"
|
flutter: ">=3.24.0"
|
||||||
|
@ -7,7 +7,7 @@ environment:
|
|||||||
sdk: ^3.5.4
|
sdk: ^3.5.4
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
# shared_preferences: ^2.3.3
|
shared_preferences: ^2.3.3
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user