Лаб 6 (вроде рабочий bloc для у страницы с описанием игры)
This commit is contained in:
parent
5bb1f898a1
commit
9abe984288
23
lib/presentation/details_page/bloc/bloc.dart
Normal file
23
lib/presentation/details_page/bloc/bloc.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:mobiles_labs_5th_semester/data/repositories/games_repository.dart';
|
||||||
|
import 'package:mobiles_labs_5th_semester/presentation/details_page/bloc/state.dart';
|
||||||
|
|
||||||
|
import 'event.dart';
|
||||||
|
|
||||||
|
class GameDetailsBloc extends Bloc<GameDetailsEvent, GameDetailsState> {
|
||||||
|
final GamesRepository repo;
|
||||||
|
|
||||||
|
GameDetailsBloc(this.repo) : super (const GameDetailsState()) {
|
||||||
|
on<LoadGameDetailsEvent>(_onLoadDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Emitter - генератор событий
|
||||||
|
Future<void> _onLoadDetails(LoadGameDetailsEvent event,
|
||||||
|
Emitter<GameDetailsState> emit) async {
|
||||||
|
String? error;
|
||||||
|
final data = await repo.loadGameData(event.gameId);
|
||||||
|
emit(state.copyWith(
|
||||||
|
gameData: data,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
9
lib/presentation/details_page/bloc/event.dart
Normal file
9
lib/presentation/details_page/bloc/event.dart
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
abstract class GameDetailsEvent {
|
||||||
|
const GameDetailsEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadGameDetailsEvent extends GameDetailsEvent {
|
||||||
|
final int? gameId;
|
||||||
|
|
||||||
|
LoadGameDetailsEvent({this.gameId});
|
||||||
|
}
|
13
lib/presentation/details_page/bloc/state.dart
Normal file
13
lib/presentation/details_page/bloc/state.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
import '../../../domain/models/game.dart';
|
||||||
|
import 'package:copy_with_extension/copy_with_extension.dart';
|
||||||
|
part 'state.g.dart';
|
||||||
|
|
||||||
|
@CopyWith()
|
||||||
|
class GameDetailsState extends Equatable {
|
||||||
|
final GameData? gameData;
|
||||||
|
const GameDetailsState({this.gameData});
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [gameData];
|
||||||
|
}
|
56
lib/presentation/details_page/bloc/state.g.dart
Normal file
56
lib/presentation/details_page/bloc/state.g.dart
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'state.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// CopyWithGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
abstract class _$GameDetailsStateCWProxy {
|
||||||
|
GameDetailsState gameData(GameData? gameData);
|
||||||
|
|
||||||
|
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `GameDetailsState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
|
||||||
|
///
|
||||||
|
/// Usage
|
||||||
|
/// ```dart
|
||||||
|
/// GameDetailsState(...).copyWith(id: 12, name: "My name")
|
||||||
|
/// ````
|
||||||
|
GameDetailsState call({
|
||||||
|
GameData? gameData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfGameDetailsState.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfGameDetailsState.copyWith.fieldName(...)`
|
||||||
|
class _$GameDetailsStateCWProxyImpl implements _$GameDetailsStateCWProxy {
|
||||||
|
const _$GameDetailsStateCWProxyImpl(this._value);
|
||||||
|
|
||||||
|
final GameDetailsState _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
GameDetailsState gameData(GameData? gameData) => this(gameData: gameData);
|
||||||
|
|
||||||
|
@override
|
||||||
|
|
||||||
|
/// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `GameDetailsState(...).copyWith.fieldName(...)` to override fields one at a time with nullification support.
|
||||||
|
///
|
||||||
|
/// Usage
|
||||||
|
/// ```dart
|
||||||
|
/// GameDetailsState(...).copyWith(id: 12, name: "My name")
|
||||||
|
/// ````
|
||||||
|
GameDetailsState call({
|
||||||
|
Object? gameData = const $CopyWithPlaceholder(),
|
||||||
|
}) {
|
||||||
|
return GameDetailsState(
|
||||||
|
gameData: gameData == const $CopyWithPlaceholder()
|
||||||
|
? _value.gameData
|
||||||
|
// ignore: cast_nullable_to_non_nullable
|
||||||
|
: gameData as GameData?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension $GameDetailsStateCopyWith on GameDetailsState {
|
||||||
|
/// Returns a callable class that can be used as follows: `instanceOfGameDetailsState.copyWith(...)` or like so:`instanceOfGameDetailsState.copyWith.fieldName(...)`.
|
||||||
|
// ignore: library_private_types_in_public_api
|
||||||
|
_$GameDetailsStateCWProxy get copyWith => _$GameDetailsStateCWProxyImpl(this);
|
||||||
|
}
|
@ -1,171 +1,88 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:mobiles_labs_5th_semester/domain/models/game.dart';
|
import 'package:mobiles_labs_5th_semester/domain/models/game.dart';
|
||||||
|
|
||||||
import '../../data/repositories/games_repository.dart';
|
import '../../data/repositories/games_repository.dart';
|
||||||
|
import 'bloc/bloc.dart';
|
||||||
|
import 'bloc/event.dart';
|
||||||
|
import 'bloc/state.dart';
|
||||||
|
|
||||||
|
class DetailsPage extends StatelessWidget {
|
||||||
class DetailsPage extends StatefulWidget {
|
|
||||||
final int? gameId;
|
final int? gameId;
|
||||||
|
|
||||||
const DetailsPage(this.gameId, {super.key});
|
const DetailsPage(this.gameId, {super.key});
|
||||||
|
|
||||||
@override
|
|
||||||
State<DetailsPage> createState() => _DetailsPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _DetailsPageState extends State<DetailsPage> {
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return BlocProvider(
|
||||||
backgroundColor: Color.fromARGB(255, 46, 65, 80),
|
create: (context) {
|
||||||
|
final bloc = GameDetailsBloc(GamesRepository());
|
||||||
|
bloc.add(LoadGameDetailsEvent(gameId: gameId!));
|
||||||
|
return bloc;
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: const Color.fromARGB(255, 46, 65, 80),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Color.fromARGB(255, 56, 90, 128),
|
backgroundColor: const Color.fromARGB(255, 56, 90, 128),
|
||||||
iconTheme: IconThemeData(color: Colors.white)
|
iconTheme: const IconThemeData(color: Colors.white),
|
||||||
),
|
),
|
||||||
body: Body(gameId: widget.gameId));
|
body: const Body(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Body extends StatefulWidget {
|
|
||||||
final int? gameId;
|
|
||||||
const Body({super.key, required this.gameId});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<Body> createState() => _BodyState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BodyState extends State<Body> {
|
class Body extends StatelessWidget {
|
||||||
late Future<GameData?> data;
|
const Body({super.key});
|
||||||
final repo = GamesRepository();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
data = repo.loadGameData(widget.gameId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Center(
|
return BlocBuilder<GameDetailsBloc, GameDetailsState>(
|
||||||
child: FutureBuilder<GameData?>(
|
builder: (context, state) {
|
||||||
future: data,
|
if (state.gameData == null) {
|
||||||
builder: (context, snapshot) => SingleChildScrollView(
|
return const Center(child: CircularProgressIndicator());
|
||||||
child: snapshot.hasData
|
}
|
||||||
? Padding(
|
final gameData = state.gameData!;
|
||||||
padding: const EdgeInsets.all(8.0),
|
return SingleChildScrollView(
|
||||||
child:
|
child: Padding(
|
||||||
Column(
|
padding: const EdgeInsets.all(8.0),
|
||||||
children: [
|
child: Column(
|
||||||
SizedBox(
|
children: [
|
||||||
height: 220,
|
SizedBox(
|
||||||
width: MediaQuery.of(context).size.width,
|
height: 220,
|
||||||
child: Image.network(
|
width: MediaQuery.of(context).size.width,
|
||||||
snapshot.data?.image ?? '',
|
child: Image.network(
|
||||||
fit: BoxFit.fill,
|
gameData.image ?? '',
|
||||||
errorBuilder: (_, __, ___) => const Placeholder(),
|
fit: BoxFit.fill,
|
||||||
),
|
errorBuilder: (_, __, ___) => const Placeholder(),
|
||||||
),
|
),
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.only(top: 12.0, bottom: 12.0),
|
Padding(
|
||||||
child: Text(
|
padding: const EdgeInsets.only(top: 12.0, bottom: 12.0),
|
||||||
snapshot.data?.name ?? '',
|
child: Text(
|
||||||
style: const TextStyle(
|
gameData.name ?? '',
|
||||||
color: Colors.white,
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
color: Colors.white,
|
||||||
fontSize: 40,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
fontSize: 40,
|
||||||
textAlign: TextAlign.center,
|
),
|
||||||
),
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
Text(
|
),
|
||||||
snapshot.data?.description ?? 'У игры нет описания',
|
Text(
|
||||||
style: const TextStyle(
|
gameData.description ?? 'У игры нет описания',
|
||||||
color: Colors.white,
|
style: const TextStyle(
|
||||||
fontSize: 24,
|
color: Colors.white,
|
||||||
),
|
fontSize: 24,
|
||||||
softWrap: true,
|
),
|
||||||
// textAlign: TextAlign.left
|
softWrap: true,
|
||||||
textAlign: TextAlign.justify
|
textAlign: TextAlign.justify,
|
||||||
),
|
),
|
||||||
]
|
],
|
||||||
|
),
|
||||||
)
|
),
|
||||||
) : const CircularProgressIndicator()
|
);
|
||||||
)
|
},
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// final data = GamesRepository().loadGameData(widget.gameId);
|
|
||||||
|
|
||||||
// return Center(
|
|
||||||
// child: FutureBuilder<GameData?> (
|
|
||||||
// future: data,
|
|
||||||
// builder: (context, snapshot) => snapshot.hasData ? Scaffold(
|
|
||||||
// appBar: AppBar(
|
|
||||||
// backgroundColor: Color.fromARGB(255, 56, 90, 128),
|
|
||||||
// iconTheme: IconThemeData(color: Colors.white)
|
|
||||||
// ),
|
|
||||||
// backgroundColor: Color.fromARGB(255, 46, 65, 80),
|
|
||||||
// //backgroundColor: Color.fromARGB(255, 56, 90, 128),
|
|
||||||
// body: Center(
|
|
||||||
// //прокрутка по вертикали на случай, если описание длинное
|
|
||||||
// child: SingleChildScrollView(
|
|
||||||
// child: Padding(
|
|
||||||
// padding: const EdgeInsets.all(8.0),
|
|
||||||
// child: Column(
|
|
||||||
// children: [
|
|
||||||
// SizedBox(
|
|
||||||
// height: 220,
|
|
||||||
// width: MediaQuery.of(context).size.width,
|
|
||||||
// child: Image.network(
|
|
||||||
// snapshot.data?.image ?? '',
|
|
||||||
// fit: BoxFit.fill,
|
|
||||||
// errorBuilder: (_, __, ___) => const Placeholder(),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Padding(
|
|
||||||
// padding: const EdgeInsets.only(top: 12.0, bottom: 12.0),
|
|
||||||
// child: Text(
|
|
||||||
// snapshot.data?.name ?? '',
|
|
||||||
// style: const TextStyle(
|
|
||||||
// color: Colors.white,
|
|
||||||
// fontWeight: FontWeight.bold,
|
|
||||||
// fontSize: 40,
|
|
||||||
// ),
|
|
||||||
// textAlign: TextAlign.center,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Text(
|
|
||||||
// snapshot.data?.description ?? 'У игры нет описания',
|
|
||||||
// style: const TextStyle(
|
|
||||||
// color: Colors.white,
|
|
||||||
// fontSize: 24,
|
|
||||||
// ),
|
|
||||||
// softWrap: true,
|
|
||||||
// // textAlign: TextAlign.left
|
|
||||||
// textAlign: TextAlign.justify
|
|
||||||
// ),
|
|
||||||
// ]
|
|
||||||
//
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// )
|
|
||||||
// ) : const CircularProgressIndicator(),
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
@ -6,7 +6,7 @@ import 'state.dart';
|
|||||||
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||||
final GamesRepository repo;
|
final GamesRepository repo;
|
||||||
|
|
||||||
//связывание метода с конкретным событием в конструкторе
|
//связывание метода _onLoadData с конкретным событием в конструкторе
|
||||||
HomeBloc(this.repo) : super (const HomeState()) {
|
HomeBloc(this.repo) : super (const HomeState()) {
|
||||||
on<HomeLoadDataEvent>(_onLoadData);
|
on<HomeLoadDataEvent>(_onLoadData);
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//!!!скорее всего надо будет заменить на stateful
|
|
||||||
class Body extends StatefulWidget {
|
class Body extends StatefulWidget {
|
||||||
const Body({super.key});
|
const Body({super.key});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user