From 9abe9842887e3690aef0912717070e8aa15ea627 Mon Sep 17 00:00:00 2001 From: ujijrujijr Date: Wed, 20 Nov 2024 00:37:34 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=B0=D0=B1=206=20(=D0=B2=D1=80=D0=BE?= =?UTF-8?q?=D0=B4=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=87=D0=B8=D0=B9=20blo?= =?UTF-8?q?c=20=D0=B4=D0=BB=D1=8F=20=D1=83=20=D1=81=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=86=D1=8B=20=D1=81=20=D0=BE=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B5=D0=BC=20=D0=B8=D0=B3=D1=80=D1=8B)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/presentation/details_page/bloc/bloc.dart | 23 ++ lib/presentation/details_page/bloc/event.dart | 9 + lib/presentation/details_page/bloc/state.dart | 13 ++ .../details_page/bloc/state.g.dart | 56 +++++ .../details_page/details_page.dart | 217 ++++++------------ lib/presentation/home_page/bloc/bloc.dart | 2 +- lib/presentation/home_page/home_page.dart | 2 +- 7 files changed, 170 insertions(+), 152 deletions(-) create mode 100644 lib/presentation/details_page/bloc/bloc.dart create mode 100644 lib/presentation/details_page/bloc/event.dart create mode 100644 lib/presentation/details_page/bloc/state.dart create mode 100644 lib/presentation/details_page/bloc/state.g.dart diff --git a/lib/presentation/details_page/bloc/bloc.dart b/lib/presentation/details_page/bloc/bloc.dart new file mode 100644 index 0000000..9a9b4b1 --- /dev/null +++ b/lib/presentation/details_page/bloc/bloc.dart @@ -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 { + final GamesRepository repo; + + GameDetailsBloc(this.repo) : super (const GameDetailsState()) { + on(_onLoadDetails); + } + + //Emitter - генератор событий + Future _onLoadDetails(LoadGameDetailsEvent event, + Emitter emit) async { + String? error; + final data = await repo.loadGameData(event.gameId); + emit(state.copyWith( + gameData: data, + )); + } +} \ No newline at end of file diff --git a/lib/presentation/details_page/bloc/event.dart b/lib/presentation/details_page/bloc/event.dart new file mode 100644 index 0000000..de76f10 --- /dev/null +++ b/lib/presentation/details_page/bloc/event.dart @@ -0,0 +1,9 @@ +abstract class GameDetailsEvent { + const GameDetailsEvent(); +} + +class LoadGameDetailsEvent extends GameDetailsEvent { + final int? gameId; + + LoadGameDetailsEvent({this.gameId}); +} diff --git a/lib/presentation/details_page/bloc/state.dart b/lib/presentation/details_page/bloc/state.dart new file mode 100644 index 0000000..4efaeea --- /dev/null +++ b/lib/presentation/details_page/bloc/state.dart @@ -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 get props => [gameData]; +} \ No newline at end of file diff --git a/lib/presentation/details_page/bloc/state.g.dart b/lib/presentation/details_page/bloc/state.g.dart new file mode 100644 index 0000000..5e531e1 --- /dev/null +++ b/lib/presentation/details_page/bloc/state.g.dart @@ -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); +} diff --git a/lib/presentation/details_page/details_page.dart b/lib/presentation/details_page/details_page.dart index af72b63..9b51458 100644 --- a/lib/presentation/details_page/details_page.dart +++ b/lib/presentation/details_page/details_page.dart @@ -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 createState() => _DetailsPageState(); -} - -class _DetailsPageState extends State { - @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 createState() => _BodyState(); -} -class _BodyState extends State { - late Future 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( - 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( + 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 ( - // 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(), -// ) -// -// ); -// } -// } +} \ No newline at end of file diff --git a/lib/presentation/home_page/bloc/bloc.dart b/lib/presentation/home_page/bloc/bloc.dart index 1c0acd5..b80db10 100644 --- a/lib/presentation/home_page/bloc/bloc.dart +++ b/lib/presentation/home_page/bloc/bloc.dart @@ -6,7 +6,7 @@ import 'state.dart'; class HomeBloc extends Bloc { final GamesRepository repo; - //связывание метода с конкретным событием в конструкторе + //связывание метода _onLoadData с конкретным событием в конструкторе HomeBloc(this.repo) : super (const HomeState()) { on(_onLoadData); } diff --git a/lib/presentation/home_page/home_page.dart b/lib/presentation/home_page/home_page.dart index a881494..451c146 100644 --- a/lib/presentation/home_page/home_page.dart +++ b/lib/presentation/home_page/home_page.dart @@ -46,7 +46,7 @@ class _HomePageState extends State { } } -//!!!скорее всего надо будет заменить на stateful + class Body extends StatefulWidget { const Body({super.key});