diff --git a/lib/app_router.dart b/lib/app_router.dart index 3c60e6e6..f0aafe9f 100644 --- a/lib/app_router.dart +++ b/lib/app_router.dart @@ -202,16 +202,14 @@ class AppRouter { path: '/chat-select-screen', name: 'chatSelectScreen', builder: (context, state) => ChatSelectScreen(), - routes: [ - GoRoute( - path: 'chat-screen', - name: 'chatScreen', - builder: (context, state) => ChatScreen(chatId: state.extra as String), - ), - ], ), ], ), + GoRoute( + path: '/chat-screen', + name: 'chatScreen', + builder: (context, state) => ChatScreen(chatId: state.extra as String), + ), GoRoute( path: '/my-settings-screen', name: 'mySettingsScreen', diff --git a/lib/core/initialization_cubit/initialization_cubit.dart b/lib/core/initialization_cubit/initialization_cubit.dart index e61d691f..cd9828ea 100644 --- a/lib/core/initialization_cubit/initialization_cubit.dart +++ b/lib/core/initialization_cubit/initialization_cubit.dart @@ -38,6 +38,9 @@ class InitializationCubit extends Cubit { await pusher.connect(); + // Channel channel = pusher.subscribe('private-direct-chat.'); + // channel.registerListener(classId, method); + emit(const InitializationState.success()); } catch (e) { emit(InitializationState.error(errorMessage: e.toString())); diff --git a/lib/features/chat/presentation/pages/chat_screen.dart b/lib/features/chat/presentation/pages/chat_screen.dart index c6ad9beb..4c4bcfe1 100644 --- a/lib/features/chat/presentation/pages/chat_screen.dart +++ b/lib/features/chat/presentation/pages/chat_screen.dart @@ -81,119 +81,121 @@ class ChatScreen extends StatelessWidget { ], ), ), - body: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - child: Container( - color: Color(0xFFF0F2F5), - width: double.maxFinite, - child: CustomScrollView( - reverse: true, - slivers: [ - SliverPadding( - padding: EdgeInsets.symmetric(vertical: 16), - sliver: SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) => ChatBubbleWidget( - text: state.chatRoomModel.messages[state.chatRoomModel.messages.length - index - 1].data, - isCurrentUser: state.chatRoomModel.users['to_chat_user']!.id != - state.chatRoomModel.messages[state.chatRoomModel.messages.length - index - 1].authorId, - mediaData: state.chatRoomModel.messages[state.chatRoomModel.messages.length - index - 1].mediaData, + body: SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: Container( + color: Color(0xFFF0F2F5), + width: double.maxFinite, + child: CustomScrollView( + reverse: true, + slivers: [ + SliverPadding( + padding: EdgeInsets.symmetric(vertical: 16), + sliver: SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) => ChatBubbleWidget( + text: state.chatRoomModel.messages[state.chatRoomModel.messages.length - index - 1].data, + isCurrentUser: state.chatRoomModel.users['to_chat_user']!.id != + state.chatRoomModel.messages[state.chatRoomModel.messages.length - index - 1].authorId, + mediaData: state.chatRoomModel.messages[state.chatRoomModel.messages.length - index - 1].mediaData, + ), + childCount: state.chatRoomModel.messages.length, ), - childCount: state.chatRoomModel.messages.length, + ), + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(width: 8), + InkWell( + onTap: () {}, + borderRadius: BorderRadiusStyle.circleBorder17, + child: Ink( + height: 32, + width: 32, + child: Icon( + Icons.attach_file_rounded, + size: 28, + color: Color(0xFF858E99), ), ), ), - ], - ), - ), - ), - Padding( - padding: EdgeInsets.symmetric(vertical: 8), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox(width: 8), - InkWell( - onTap: () {}, - borderRadius: BorderRadiusStyle.circleBorder17, - child: Ink( - height: 32, - width: 32, - child: Icon( - Icons.attach_file_rounded, - size: 28, - color: Color(0xFF858E99), - ), - ), - ), - SizedBox(width: 8), - SizedBox( - width: mediaQueryData.size.width - 96, - child: TextFormField( - maxLines: 5, - minLines: 1, - keyboardType: TextInputType.multiline, - style: TextStyle( - fontSize: 16, - fontFamily: 'Mulish', - fontWeight: FontWeight.w400, - color: Colors.black, - ), - decoration: InputDecoration( - contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 4), - hintText: 'Сообщение', - hintStyle: TextStyle( + SizedBox(width: 8), + SizedBox( + width: mediaQueryData.size.width - 96, + child: TextFormField( + maxLines: 5, + minLines: 1, + keyboardType: TextInputType.multiline, + style: TextStyle( fontSize: 16, fontFamily: 'Mulish', fontWeight: FontWeight.w400, - color: Color(0xFFAEAEB2), + color: Colors.black, ), - filled: true, - border: OutlineInputBorder( - borderRadius: BorderRadiusStyle.circleBorder17, - borderSide: BorderSide( - color: Color(0xFFD1D1D6), - width: 1, + decoration: InputDecoration( + contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 4), + hintText: 'Сообщение', + hintStyle: TextStyle( + fontSize: 16, + fontFamily: 'Mulish', + fontWeight: FontWeight.w400, + color: Color(0xFFAEAEB2), ), - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadiusStyle.circleBorder17, - borderSide: BorderSide( - color: Color(0xFFD1D1D6), - width: 1, + filled: true, + border: OutlineInputBorder( + borderRadius: BorderRadiusStyle.circleBorder17, + borderSide: BorderSide( + color: Color(0xFFD1D1D6), + width: 1, + ), ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadiusStyle.circleBorder17, - borderSide: BorderSide( - color: Color(0xFFD1D1D6), - width: 1, + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadiusStyle.circleBorder17, + borderSide: BorderSide( + color: Color(0xFFD1D1D6), + width: 1, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadiusStyle.circleBorder17, + borderSide: BorderSide( + color: Color(0xFFD1D1D6), + width: 1, + ), ), ), ), ), - ), - SizedBox(width: 8), - InkWell( - borderRadius: BorderRadiusStyle.circleBorder17, - onTap: () {}, - child: Ink( - height: 32, - width: 32, - child: Icon( - Icons.send_outlined, - size: 28, - color: Color(0xFF858E99), + SizedBox(width: 8), + InkWell( + borderRadius: BorderRadiusStyle.circleBorder17, + onTap: () {}, + child: Ink( + height: 32, + width: 32, + child: Icon( + Icons.send_outlined, + size: 28, + color: Color(0xFF858E99), + ), ), ), - ), - SizedBox(width: 8), - ], + SizedBox(width: 8), + ], + ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/features/chat/presentation/pages/chat_select_screen/bloc/chat_select_bloc.dart b/lib/features/chat/presentation/pages/chat_select_screen/bloc/chat_select_bloc.dart index ba44ade1..d041db4f 100644 --- a/lib/features/chat/presentation/pages/chat_select_screen/bloc/chat_select_bloc.dart +++ b/lib/features/chat/presentation/pages/chat_select_screen/bloc/chat_select_bloc.dart @@ -27,17 +27,22 @@ class ChatSelectBloc extends Bloc { List chats = []; for (int i = 0; i < chatRooms.length; i++) { String text = chatRooms[i]['last_message']['data']; - if (chatRooms[i]['last_message']['is_author_from_user']) { + if (chatRooms[i]['last_message']['is_author_message_auth_user'] != null) { text = "Вы: " + text; } - chats.add(ChatItemModel( + chats.add( + ChatItemModel( id: chatRooms[i]['id'], - userImage: chatRooms[i]['users']['to_chat_user'] - ['profile_photo_path'], + userImage: chatRooms[i]['users']['to_chat_user']['profile_photo_path'], username: chatRooms[i]['users']['to_chat_user']['name'], dateText: DateFormat('dd.MM').format( - DateTime.parse(chatRooms[i]['last_message']['updated_at'])), - greetingText: text)); + DateTime.parse( + chatRooms[i]['last_message']['updated_at'], + ), + ), + greetingText: text, + ), + ); } return chats; } @@ -75,8 +80,7 @@ class ChatSelectBloc extends Bloc { } } else { // Один или несколько ключевых полей отсутствуют, обрабатываем ошибку - emit(ChatSelectErrorState( - 'Некоторые необходимые данные отсутствуют.')); + emit(ChatSelectErrorState('Некоторые необходимые данные отсутствуют.')); } } else { // Статус ответа не равен 200, обрабатываем ошибку diff --git a/lib/features/chat/presentation/pages/chat_select_screen/chat_select_screen.dart b/lib/features/chat/presentation/pages/chat_select_screen/chat_select_screen.dart index 74911c3d..60b889a7 100644 --- a/lib/features/chat/presentation/pages/chat_select_screen/chat_select_screen.dart +++ b/lib/features/chat/presentation/pages/chat_select_screen/chat_select_screen.dart @@ -64,7 +64,10 @@ class ChatSelectScreen extends StatelessWidget { ), ); } else if (state is ChatSelectErrorState) { - return Center(child: Text(state.errorMessage)); + return Padding( + padding: const EdgeInsets.all(16), + child: Center(child: Text(state.errorMessage)), + ); } else { return Scaffold( body: Center( diff --git a/lib/features/chat/presentation/pages/chat_select_screen/models/chat_entry.dart b/lib/features/chat/presentation/pages/chat_select_screen/models/chat_entry.dart index 6738afb8..cffee89a 100644 --- a/lib/features/chat/presentation/pages/chat_select_screen/models/chat_entry.dart +++ b/lib/features/chat/presentation/pages/chat_select_screen/models/chat_entry.dart @@ -4,26 +4,23 @@ import 'package:eatvio_app/core/app_export.dart'; // ignore_for_file: must_be_immutable class ChatItemModel { - ChatItemModel( - {this.userImage, - this.username, - this.dateText, - this.greetingText, - required this.id}) { + String? userImage; + String? username; + String? dateText; + String? greetingText; + String id; + + ChatItemModel({ + this.userImage, + this.username, + this.dateText, + this.greetingText, + required this.id, + }) { userImage = userImage ?? ImageConstant.imageNotFound; username = username; dateText = dateText; greetingText = greetingText; id = id; } - - String? userImage; - - String? username; - - String? dateText; - - String? greetingText; - - String id; } diff --git a/lib/features/chat/presentation/pages/chat_select_screen/models/chat_select_model.dart b/lib/features/chat/presentation/pages/chat_select_screen/models/chat_select_model.dart index c95b52ee..8a0ae045 100644 --- a/lib/features/chat/presentation/pages/chat_select_screen/models/chat_select_model.dart +++ b/lib/features/chat/presentation/pages/chat_select_screen/models/chat_select_model.dart @@ -5,9 +5,11 @@ import 'package:equatable/equatable.dart'; /// This class defines the variables used in the [chat_select_screen], /// and is typically used to hold data that is passed between different parts of the application. + class ChatSelectModel extends Equatable { ChatSelectModel({this.chatList = const []}); List chatList; + ChatSelectModel copyWith({List? chatList}) { return ChatSelectModel( chatList: chatList ?? this.chatList, diff --git a/lib/features/chat/presentation/pages/chat_select_screen/widgets/chat_entry_widget.dart b/lib/features/chat/presentation/pages/chat_select_screen/widgets/chat_entry_widget.dart index fbd6b1b0..87a46ab5 100644 --- a/lib/features/chat/presentation/pages/chat_select_screen/widgets/chat_entry_widget.dart +++ b/lib/features/chat/presentation/pages/chat_select_screen/widgets/chat_entry_widget.dart @@ -15,12 +15,13 @@ class ChatEntryWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return GestureDetector( - onTap: () => GoRouter.of(context).goNamed( + return InkWell( + borderRadius: BorderRadiusStyle.circleBorder8, + onTap: () => GoRouter.of(context).pushNamed( 'chatScreen', extra: chatEntryObj.id.toString(), ), - child: Container( + child: Ink( padding: EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadiusStyle.circleBorder8, diff --git a/lib/features/chat/presentation/pages/photo_view_screen.dart b/lib/features/chat/presentation/pages/photo_view_screen.dart index 229ced53..f576a586 100644 --- a/lib/features/chat/presentation/pages/photo_view_screen.dart +++ b/lib/features/chat/presentation/pages/photo_view_screen.dart @@ -1,6 +1,7 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:dismissible_page/dismissible_page.dart'; import 'package:eatvio_app/core/app_export.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:go_router/go_router.dart'; import 'package:photo_view/photo_view.dart'; @@ -34,37 +35,32 @@ class _PhotoViewScreenState extends State { @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.black, - appBar: AppBar( - centerTitle: true, - systemOverlayStyle: SystemUiOverlayStyle( - statusBarColor: Colors.black, - statusBarBrightness: Brightness.dark, - statusBarIconBrightness: Brightness.light, + return DismissiblePage( + minScale: 1, + onDismissed: () => GoRouter.of(context).pop(), + direction: DismissiblePageDismissDirection.vertical, + isFullScreen: true, + child: PhotoViewGallery.builder( + backgroundDecoration: BoxDecoration( + color: Colors.transparent, ), - backgroundColor: Colors.black, - foregroundColor: Colors.white, - title: Text( - (imageIndex + 1).toString() + ' из ' + widget.imageUrls.length.toString(), - ), - ), - body: Dismissible( - direction: DismissDirection.vertical, - key: const Key('key'), - onDismissed: (_) => GoRouter.of(context).pop(), - resizeDuration: Duration(microseconds: 1), - child: Container( - child: PhotoViewGallery.builder( - scrollPhysics: const BouncingScrollPhysics(), - builder: (BuildContext context, int index) { - return PhotoViewGalleryPageOptions( - imageProvider: NetworkImage(widget.imageUrls[index]), - initialScale: PhotoViewComputedScale.contained, - minScale: PhotoViewComputedScale.contained, - heroAttributes: PhotoViewHeroAttributes(tag: widget.imageUrls[index]), - errorBuilder: (context, object, stackTrace) { - return Column( + scrollPhysics: const BouncingScrollPhysics(), + builder: (BuildContext context, int index) { + return PhotoViewGalleryPageOptions( + imageProvider: CachedNetworkImageProvider( + widget.imageUrls[index], + ), + initialScale: PhotoViewComputedScale.contained, + minScale: PhotoViewComputedScale.contained, + heroAttributes: PhotoViewHeroAttributes( + tag: widget.imageUrls[index], + transitionOnUserGestures: true, + ), + errorBuilder: (context, object, stackTrace) { + return Scaffold( + backgroundColor: Colors.black, + body: SafeArea( + child: Column( children: [ SizedBox(height: 32), Text('Файл'), @@ -96,28 +92,28 @@ class _PhotoViewScreenState extends State { ), ), ], - ); - }, + ), + ), ); }, - itemCount: widget.imageUrls.length, - loadingBuilder: (context, event) => Center( - child: Container( - width: 20.0, - height: 20.0, - child: CircularProgressIndicator( - value: event == null ? 0 : event.cumulativeBytesLoaded / event.expectedTotalBytes!, - ), - ), + ); + }, + itemCount: widget.imageUrls.length, + loadingBuilder: (context, event) => Center( + child: Container( + width: 20.0, + height: 20.0, + child: CircularProgressIndicator( + value: event == null ? 0 : event.cumulativeBytesLoaded / event.expectedTotalBytes!, ), - pageController: pageController, - onPageChanged: (page) { - setState(() { - imageIndex = page; - }); - }, ), ), + pageController: pageController, + onPageChanged: (page) { + setState(() { + imageIndex = page; + }); + }, ), ); } diff --git a/lib/features/chat/presentation/widgets/chat_bubble_widget.dart b/lib/features/chat/presentation/widgets/chat_bubble_widget.dart index 127795cc..39a13253 100644 --- a/lib/features/chat/presentation/widgets/chat_bubble_widget.dart +++ b/lib/features/chat/presentation/widgets/chat_bubble_widget.dart @@ -1,8 +1,9 @@ import 'package:cached_network_image/cached_network_image.dart'; +import 'package:dismissible_page/dismissible_page.dart'; +import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart'; import 'package:eatvio_app/theme/app_decoration.dart'; import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; -import 'package:go_router/go_router.dart'; import 'package:url_launcher/url_launcher.dart'; class ChatBubbleWidget extends StatelessWidget { @@ -71,18 +72,21 @@ class ChatBubbleWidget extends StatelessWidget { } return GestureDetector( onTap: () { - GoRouter.of(context).pushNamed( - 'photoViewScreen', - extra: mediaData!.map((e) => dotenv.env['STORAGE_URL']! + e.toString()).toList(), - pathParameters: { - 'index': index.toString(), - }, + context.pushTransparentRoute( + PhotoViewScreen( + imageUrls: mediaData!.map((e) => dotenv.env['STORAGE_URL']! + e.toString()).toList(), + index: index, + ), ); }, - child: ClipRRect( - borderRadius: BorderRadiusStyle.roundedBorder8, - child: CachedNetworkImage( - imageUrl: dotenv.env['STORAGE_URL']! + '${mediaData![index]}', + child: Hero( + tag: dotenv.env['STORAGE_URL']! + '${mediaData![index]}', + transitionOnUserGestures: true, + child: ClipRRect( + borderRadius: BorderRadiusStyle.roundedBorder8, + child: CachedNetworkImage( + imageUrl: dotenv.env['STORAGE_URL']! + '${mediaData![index]}', + ), ), ), ); diff --git a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart index 48d1ed62..38b15615 100644 --- a/lib/presentation/profile/my_profile_screen/my_profile_screen.dart +++ b/lib/presentation/profile/my_profile_screen/my_profile_screen.dart @@ -175,13 +175,13 @@ class MyProfileScreen extends StatelessWidget { } addImage(BuildContext context) async { - final picker = ImagePicker(); - List? images = await picker.pickMultiImage(); - if (images.isNotEmpty) { - for (var image in images) { - context.read().add(UploadAvatar(image)); - } + final picker = ImagePicker(); + List? images = await picker.pickMultiImage(); + if (images.isNotEmpty) { + for (var image in images) { + context.read().add(UploadAvatar(image)); } + } } onTapSettings(BuildContext context) { @@ -192,7 +192,7 @@ class MyProfileScreen extends StatelessWidget { _buildCarousel(BuildContext contex, MyProfileLoadedState state) { return CarouselSlider( - options: CarouselOptions(height: 320.0), + options: CarouselOptions(height: 340), items: [1, 2, 3].map((chartType) { return Builder( builder: (BuildContext context) { diff --git a/pubspec.yaml b/pubspec.yaml index ad2e28fd..17ba3aae 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A new Flutter project. version: 0.0.0+1 environment: - sdk: '>=3.3.4 <4.0.0' + sdk: ">=3.3.4 <4.0.0" dependencies: flutter: @@ -60,8 +60,9 @@ dependencies: dio: ^5.4.3+1 # websocket pusher_client: ^2.0.0 - # photo gallery viewer + # photo gallery viewer + dismissible page photo_view: ^0.15.0 + dismissible_page: ^1.0.2 #url launcher url_launcher: ^6.3.0 @@ -94,4 +95,4 @@ flutter: - asset: assets/fonts/MulishRegular.ttf weight: 400 - asset: assets/fonts/MulishSemiBold.ttf - weight: 600 \ No newline at end of file + weight: 600