6 лаба сделана (поиск вроде тоже работает)
This commit is contained in:
parent
69f28b9297
commit
4014a00a68
49
lib/bloc.dart
Normal file
49
lib/bloc.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'events.dart';
|
||||||
|
import 'state.dart';
|
||||||
|
import 'character_service.dart';
|
||||||
|
import 'character.dart';
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class DebouncedSearchCubit extends Cubit<String> {
|
||||||
|
DebouncedSearchCubit() : super('');
|
||||||
|
|
||||||
|
Timer? _debounce;
|
||||||
|
|
||||||
|
// Метод для обновления поиска с задержкой
|
||||||
|
void search(String query) {
|
||||||
|
if (_debounce?.isActive ?? false) _debounce?.cancel();
|
||||||
|
_debounce = Timer(const Duration(milliseconds: 500), () {
|
||||||
|
emit(query);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() {
|
||||||
|
_debounce?.cancel();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||||
|
final CharacterService characterService;
|
||||||
|
|
||||||
|
HomeBloc(this.characterService) : super(const HomeState()) {
|
||||||
|
on<HomeLoadDataEvent>(_onLoadData);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onLoadData(HomeLoadDataEvent event, Emitter<HomeState> emit) async {
|
||||||
|
emit(state.copyWith(status: HomeStatus.loading));
|
||||||
|
|
||||||
|
try {
|
||||||
|
final characters = await characterService.getCharacters(search: event.searchQuery);
|
||||||
|
print('Characters loaded: $characters'); // Отладочный вывод
|
||||||
|
emit(state.copyWith(status: HomeStatus.loaded, characters: characters));
|
||||||
|
} catch (e) {
|
||||||
|
print('Error: $e');
|
||||||
|
emit(state.copyWith(status: HomeStatus.error, errorMessage: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -59,7 +59,6 @@ class Character {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Survivor extends Character {
|
class Survivor extends Character {
|
||||||
Survivor({
|
Survivor({
|
||||||
required String name,
|
required String name,
|
||||||
|
@ -7,16 +7,31 @@ const String baseUrl = 'http://192.168.1.83:5000'; // IP-адрес вмест
|
|||||||
class CharacterService {
|
class CharacterService {
|
||||||
Future<List<Character>> getCharacters({String search = ''}) async {
|
Future<List<Character>> getCharacters({String search = ''}) async {
|
||||||
try {
|
try {
|
||||||
final response = await http.get(Uri.parse('$baseUrl/characters?search=$search'));
|
// Формируем URL с параметром поиска
|
||||||
|
final uri = Uri.parse('$baseUrl/characters?search=$search');
|
||||||
|
|
||||||
|
// Выполняем HTTP-запрос
|
||||||
|
final response = await http.get(uri);
|
||||||
|
|
||||||
|
// Логирование данных для отладки
|
||||||
|
print('Response status: ${response.statusCode}');
|
||||||
|
print('Response body: ${response.body}'); // Выводим тело ответа для анализа
|
||||||
|
|
||||||
|
// Проверяем успешный ответ от сервера
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final List<dynamic> data = json.decode(response.body);
|
final List<dynamic> data = json.decode(response.body);
|
||||||
|
print('Characters received: $data'); // Печать данных
|
||||||
|
|
||||||
|
// Возвращаем список объектов Character
|
||||||
return data.map((item) => Character.fromJson(item)).toList();
|
return data.map((item) => Character.fromJson(item)).toList();
|
||||||
} else {
|
} else {
|
||||||
throw Exception('Ошибка загрузки данных с сервера. Статус: ${response.statusCode}');
|
// Ошибка, если сервер вернул не 200 статус
|
||||||
|
print('Error: Server responded with status ${response.statusCode}');
|
||||||
|
throw Exception('Ошибка загрузки данных с сервера');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Ошибка при получении данных: $e');
|
// Обработка ошибок при выполнении запроса
|
||||||
|
print('Error fetching characters: $e');
|
||||||
throw Exception('Не удалось загрузить персонажей');
|
throw Exception('Не удалось загрузить персонажей');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
lib/events.dart
Normal file
17
lib/events.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
abstract class HomeEvent extends Equatable {
|
||||||
|
const HomeEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeLoadDataEvent extends HomeEvent {
|
||||||
|
final String searchQuery;
|
||||||
|
|
||||||
|
const HomeLoadDataEvent({this.searchQuery = ''});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [searchQuery];
|
||||||
|
}
|
208
lib/main.dart
208
lib/main.dart
@ -1,74 +1,72 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'character.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'bloc.dart';
|
||||||
|
import 'events.dart';
|
||||||
|
import 'state.dart';
|
||||||
import 'character_service.dart';
|
import 'character_service.dart';
|
||||||
import 'pages/CharacterDetailPage.dart';
|
import 'character.dart';
|
||||||
|
import 'pages/character_detail_page.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(
|
||||||
|
MultiBlocProvider(
|
||||||
|
providers: [
|
||||||
|
BlocProvider<HomeBloc>(
|
||||||
|
create: (_) => HomeBloc(CharacterService()),
|
||||||
|
),
|
||||||
|
BlocProvider<DebouncedSearchCubit>(
|
||||||
|
create: (_) => DebouncedSearchCubit(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: MyApp(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void main() => runApp(MyApp());
|
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'Identity V Characters',
|
title: 'My App',
|
||||||
home: MyHomePage(title: 'Персонажи Identity V'),
|
home: MyHomePage(title: 'Identity'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyHomePage extends StatefulWidget {
|
class MyHomePage extends StatelessWidget {
|
||||||
MyHomePage({Key? key, required this.title}) : super(key: key);
|
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
@override
|
MyHomePage({required this.title});
|
||||||
_MyHomePageState createState() => _MyHomePageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
|
||||||
final CharacterService _characterService = CharacterService();
|
|
||||||
late Future<List<Character>> _futureCharacters;
|
|
||||||
final TextEditingController _searchController = TextEditingController();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_futureCharacters = _characterService.getCharacters();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _searchCharacters(String query) {
|
|
||||||
setState(() {
|
|
||||||
_futureCharacters = _characterService.getCharacters(search: query);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// Загружаем данные сразу после инициализации страницы
|
||||||
|
context.read<HomeBloc>().add(HomeLoadDataEvent());
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(widget.title),
|
title: Text(title),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.search),
|
icon: Icon(Icons.search),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showSearch(
|
showSearch(
|
||||||
context: context,
|
context: context,
|
||||||
delegate: CharacterSearchDelegate(_searchCharacters),
|
delegate: CharacterSearchDelegate(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: FutureBuilder<List<Character>>(
|
body: BlocBuilder<HomeBloc, HomeState>(
|
||||||
future: _futureCharacters,
|
builder: (context, state) {
|
||||||
builder: (context, snapshot) {
|
if (state.status == HomeStatus.loading) {
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
||||||
return Center(child: CircularProgressIndicator());
|
return Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasError) {
|
} else if (state.status == HomeStatus.error) {
|
||||||
return Center(child: Text('Ошибка: ${snapshot.error}'));
|
return Center(child: Text('Ошибка: ${state.errorMessage}'));
|
||||||
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
} else if (state.status == HomeStatus.loaded) {
|
||||||
return Center(child: Text('Нет персонажей'));
|
final characters = state.characters;
|
||||||
} else {
|
|
||||||
final characters = snapshot.data!;
|
|
||||||
|
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: characters.length,
|
itemCount: characters.length,
|
||||||
@ -81,28 +79,8 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
),
|
),
|
||||||
title: Text(character.name),
|
title: Text(character.name),
|
||||||
subtitle: Text(character.typeString),
|
subtitle: Text(character.typeString),
|
||||||
trailing: IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
character.isLiked ? Icons.favorite : Icons.favorite_border,
|
|
||||||
color: character.isLiked ? Colors.red : null,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
character.isLiked = !character.isLiked;
|
|
||||||
});
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(
|
|
||||||
character.isLiked
|
|
||||||
? '${character.name} понравился вам!'
|
|
||||||
: '${character.name} убран из лайков.',
|
|
||||||
),
|
|
||||||
duration: Duration(seconds: 2),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
// Переход на страницу с деталями персонажа
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
@ -113,6 +91,8 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return Center(child: Text('Нет данных.'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -121,40 +101,87 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CharacterSearchDelegate extends SearchDelegate {
|
class CharacterSearchDelegate extends SearchDelegate {
|
||||||
final Function(String) onSearch;
|
|
||||||
|
|
||||||
CharacterSearchDelegate(this.onSearch);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildSuggestions(BuildContext context) {
|
Widget buildSuggestions(BuildContext context) {
|
||||||
return ListView();
|
// Показываем предложения на основе текущего запроса
|
||||||
|
return BlocProvider<HomeBloc>(
|
||||||
|
create: (context) => HomeBloc(CharacterService()),
|
||||||
|
child: BlocBuilder<HomeBloc, HomeState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final suggestions = state.characters
|
||||||
|
.where((character) => character.name.toLowerCase().contains(query.toLowerCase()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: suggestions.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final character = suggestions[index];
|
||||||
|
return ListTile(
|
||||||
|
title: Text(character.name),
|
||||||
|
subtitle: Text(character.typeString),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => CharacterDetailPage(character: character),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildResults(BuildContext context) {
|
Widget buildResults(BuildContext context) {
|
||||||
onSearch(query); // Выполняем поиск
|
// Отправляем запрос с задержкой
|
||||||
return FutureBuilder<List<Character>>(
|
final debouncedSearchCubit = context.read<DebouncedSearchCubit>();
|
||||||
future: CharacterService().getCharacters(search: query), // Запрашиваем персонажей с фильтром
|
debouncedSearchCubit.search(query);
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
return BlocBuilder<DebouncedSearchCubit, String>(
|
||||||
return Center(child: CircularProgressIndicator());
|
builder: (context, searchQuery) {
|
||||||
} else if (snapshot.hasError) {
|
// Отправляем запрос на сервер через HomeBloc
|
||||||
return Center(child: Text('Ошибка: ${snapshot.error}'));
|
if (searchQuery.isNotEmpty) {
|
||||||
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
context.read<HomeBloc>().add(HomeLoadDataEvent(searchQuery: searchQuery));
|
||||||
return Center(child: Text('Нет результатов для "$query"'));
|
|
||||||
} else {
|
|
||||||
final characters = snapshot.data!;
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: characters.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final character = characters[index];
|
|
||||||
return ListTile(
|
|
||||||
title: Text(character.name),
|
|
||||||
subtitle: Text(character.typeString),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return BlocBuilder<HomeBloc, HomeState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state.status == HomeStatus.loading) {
|
||||||
|
return Center(child: CircularProgressIndicator());
|
||||||
|
} else if (state.status == HomeStatus.error) {
|
||||||
|
return Center(child: Text('Ошибка: ${state.errorMessage}'));
|
||||||
|
} else if (state.status == HomeStatus.loaded) {
|
||||||
|
final characters = state.characters
|
||||||
|
.where((character) => character.name.toLowerCase().contains(searchQuery.toLowerCase()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: characters.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final character = characters[index];
|
||||||
|
return ListTile(
|
||||||
|
title: Text(character.name),
|
||||||
|
subtitle: Text(character.typeString),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => CharacterDetailPage(character: character),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Center(child: Text('Нет результатов'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -165,7 +192,8 @@ class CharacterSearchDelegate extends SearchDelegate {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.clear),
|
icon: Icon(Icons.clear),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
query = ''; // Очищаем запрос
|
query = ''; // Очистить запрос
|
||||||
|
showSuggestions(context); // Показать предложения
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@ -176,7 +204,7 @@ class CharacterSearchDelegate extends SearchDelegate {
|
|||||||
return IconButton(
|
return IconButton(
|
||||||
icon: Icon(Icons.arrow_back),
|
icon: Icon(Icons.arrow_back),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
close(context, null); // Закрываем поиск
|
close(context, null); // Закрыть поиск
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../character.dart';
|
import '../character.dart'; // Убедитесь, что путь правильный
|
||||||
|
|
||||||
class CharacterDetailPage extends StatelessWidget {
|
class CharacterDetailPage extends StatelessWidget {
|
||||||
final Character character;
|
final Character character;
|
||||||
|
|
||||||
CharacterDetailPage({required this.character});
|
// Конструктор с обязательным параметром
|
||||||
|
const CharacterDetailPage({Key? key, required this.character}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -28,7 +29,6 @@ class CharacterDetailPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
|
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
character.name, // Имя персонажа
|
character.name, // Имя персонажа
|
||||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
33
lib/state.dart
Normal file
33
lib/state.dart
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../character.dart'; // Добавим импорт для Character
|
||||||
|
|
||||||
|
enum HomeStatus { initial, loading, loaded, error }
|
||||||
|
|
||||||
|
class HomeState extends Equatable {
|
||||||
|
final HomeStatus status;
|
||||||
|
final List<Character> characters; // Список персонажей
|
||||||
|
final String errorMessage;
|
||||||
|
|
||||||
|
const HomeState({
|
||||||
|
this.status = HomeStatus.initial,
|
||||||
|
this.characters = const [],
|
||||||
|
this.errorMessage = '',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Метод для обновления состояния
|
||||||
|
HomeState copyWith({
|
||||||
|
HomeStatus? status,
|
||||||
|
List<Character>? characters,
|
||||||
|
String? errorMessage,
|
||||||
|
}) {
|
||||||
|
return HomeState(
|
||||||
|
status: status ?? this.status,
|
||||||
|
characters: characters ?? this.characters,
|
||||||
|
errorMessage: errorMessage ?? this.errorMessage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [status, characters, errorMessage];
|
||||||
|
}
|
40
pubspec.lock
40
pubspec.lock
@ -9,6 +9,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.11.0"
|
version: "2.11.0"
|
||||||
|
bloc:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: bloc
|
||||||
|
sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.1.4"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -49,6 +57,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.8"
|
version: "1.0.8"
|
||||||
|
equatable:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: equatable
|
||||||
|
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.7"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -62,6 +78,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_bloc:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_bloc
|
||||||
|
sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.1.6"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -147,6 +171,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0"
|
version: "1.15.0"
|
||||||
|
nested:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: nested
|
||||||
|
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -155,6 +187,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.9.0"
|
||||||
|
provider:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: provider
|
||||||
|
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.2"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -33,7 +33,8 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
http: ^1.2.2
|
http: ^1.2.2
|
||||||
|
equatable: ^2.0.5
|
||||||
|
flutter_bloc: ^8.1.5
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
|
Loading…
Reference in New Issue
Block a user