Лаб 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_bloc/flutter_bloc.dart';
|
||||
import 'package:mobiles_labs_5th_semester/domain/models/game.dart';
|
||||
|
||||
import '../../data/repositories/games_repository.dart';
|
||||
import 'bloc/bloc.dart';
|
||||
import 'bloc/event.dart';
|
||||
import 'bloc/state.dart';
|
||||
|
||||
|
||||
class DetailsPage extends StatefulWidget {
|
||||
class DetailsPage extends StatelessWidget {
|
||||
final int? gameId;
|
||||
|
||||
const DetailsPage(this.gameId, {super.key});
|
||||
|
||||
@override
|
||||
State<DetailsPage> createState() => _DetailsPageState();
|
||||
}
|
||||
|
||||
class _DetailsPageState extends State<DetailsPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Color.fromARGB(255, 46, 65, 80),
|
||||
return BlocProvider(
|
||||
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(
|
||||
backgroundColor: Color.fromARGB(255, 56, 90, 128),
|
||||
iconTheme: IconThemeData(color: Colors.white)
|
||||
backgroundColor: const Color.fromARGB(255, 56, 90, 128),
|
||||
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> {
|
||||
late Future<GameData?> data;
|
||||
final repo = GamesRepository();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
data = repo.loadGameData(widget.gameId);
|
||||
}
|
||||
class Body extends StatelessWidget {
|
||||
const Body({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: FutureBuilder<GameData?>(
|
||||
future: data,
|
||||
builder: (context, snapshot) => SingleChildScrollView(
|
||||
child: snapshot.hasData
|
||||
? 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()
|
||||
)
|
||||
)
|
||||
return BlocBuilder<GameDetailsBloc, GameDetailsState>(
|
||||
builder: (context, state) {
|
||||
if (state.gameData == null) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
final gameData = state.gameData!;
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 220,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Image.network(
|
||||
gameData.image ?? '',
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder: (_, __, ___) => const Placeholder(),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12.0, bottom: 12.0),
|
||||
child: Text(
|
||||
gameData.name ?? '',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 40,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
gameData.description ?? 'У игры нет описания',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 24,
|
||||
),
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.justify,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 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> {
|
||||
final GamesRepository repo;
|
||||
|
||||
//связывание метода с конкретным событием в конструкторе
|
||||
//связывание метода _onLoadData с конкретным событием в конструкторе
|
||||
HomeBloc(this.repo) : super (const HomeState()) {
|
||||
on<HomeLoadDataEvent>(_onLoadData);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class _HomePageState extends State<HomePage> {
|
||||
}
|
||||
}
|
||||
|
||||
//!!!скорее всего надо будет заменить на stateful
|
||||
|
||||
class Body extends StatefulWidget {
|
||||
const Body({super.key});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user