Лаб 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,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(),
// )
//
// );
// }
// }
}

View File

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

View File

@ -46,7 +46,7 @@ class _HomePageState extends State<HomePage> {
}
}
//!!!скорее всего надо будет заменить на stateful
class Body extends StatefulWidget {
const Body({super.key});