Лаб 6 (вроде рабочий bloc для у страницы с описанием игры)

This commit is contained in:
ujijrujijr 2024-11-20 00:37:34 +04:00
parent 5bb1f898a1
commit 9abe984288
7 changed files with 170 additions and 152 deletions

View 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,
));
}
}

View File

@ -0,0 +1,9 @@
abstract class GameDetailsEvent {
const GameDetailsEvent();
}
class LoadGameDetailsEvent extends GameDetailsEvent {
final int? gameId;
LoadGameDetailsEvent({this.gameId});
}

View 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];
}

View 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);
}

View File

@ -1,71 +1,58 @@
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> {
late Future<GameData?> data;
final repo = GamesRepository();
@override class Body extends StatelessWidget {
void initState() { const Body({super.key});
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!;
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: child: Column(
Column(
children: [ children: [
SizedBox( SizedBox(
height: 220, height: 220,
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
child: Image.network( child: Image.network(
snapshot.data?.image ?? '', gameData.image ?? '',
fit: BoxFit.fill, fit: BoxFit.fill,
errorBuilder: (_, __, ___) => const Placeholder(), errorBuilder: (_, __, ___) => const Placeholder(),
), ),
@ -73,7 +60,7 @@ class _BodyState extends State<Body> {
Padding( Padding(
padding: const EdgeInsets.only(top: 12.0, bottom: 12.0), padding: const EdgeInsets.only(top: 12.0, bottom: 12.0),
child: Text( child: Text(
snapshot.data?.name ?? '', gameData.name ?? '',
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -83,89 +70,19 @@ class _BodyState extends State<Body> {
), ),
), ),
Text( Text(
snapshot.data?.description ?? 'У игры нет описания', gameData.description ?? 'У игры нет описания',
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 24, fontSize: 24,
), ),
softWrap: true, softWrap: true,
// textAlign: TextAlign.left 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(),
// )
//
// );
// }
// }

View File

@ -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);
} }

View File

@ -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});