diff --git a/lib/core/initialization_cubit/initialization_cubit.dart b/lib/core/initialization_cubit/initialization_cubit.dart index 7ab68632..4db6546f 100644 --- a/lib/core/initialization_cubit/initialization_cubit.dart +++ b/lib/core/initialization_cubit/initialization_cubit.dart @@ -3,29 +3,13 @@ import 'package:eatvio_app/core/app_export.dart'; import 'package:eatvio_app/core/initialization_cubit/initialization_state.dart'; import 'package:eatvio_app/core/token_storage.dart'; import 'package:eatvio_app/features/chat/repositories/chat_repository.dart'; -import 'package:dio/dio.dart'; class InitializationCubit extends Cubit { final ChatRepository chatRepository; InitializationCubit({required this.chatRepository}) : super(const InitializationState.loading()); - - // final myPrivateChannel = client.privateChannel( - // 'private-new-chat-messages.${wsUrl.userId}', - // authorizationDelegate: EndpointAuthorizableChannelTokenAuthorizationDelegate.forPrivateChannel( - // authorizationEndpoint: Uri.parse('https://mobile-stage.eatvio.ru/broadcasting/auth'), - // headers: { - // 'Authorization': 'Bearer ${await TokenStorage.getTokenFromStorage()}', - // }, - // ), - // ); - // myPrivateChannel.subscribe(); - // myPrivateChannel.bindToAll().listen((event) { - // print(event.name); - // }); - - runInitialization() async { + Future runInitialization() async { try { await TokenStorage.haveTokenInStorage(); final wsUrl = await chatRepository.getWebsocket(); @@ -63,6 +47,7 @@ class InitializationCubit extends Cubit { emit(InitializationState.error( errorMessage: e.toString(), )); + rethrow; } } } diff --git a/lib/features/blog_post/services/blog_post_service.g.dart b/lib/features/blog_post/services/blog_post_service.g.dart index 7af46076..c99e7859 100644 --- a/lib/features/blog_post/services/blog_post_service.g.dart +++ b/lib/features/blog_post/services/blog_post_service.g.dart @@ -6,7 +6,7 @@ part of 'blog_post_service.dart'; // RetrofitGenerator // ************************************************************************** -// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers +// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element class _BlogPostService implements BlogPostService { _BlogPostService( @@ -41,8 +41,8 @@ class _BlogPostService implements BlogPostService { _dio.options.baseUrl, baseUrl, )))); - final value = BlogPostModel.fromJson(_result.data!); - return value; + final _value = BlogPostModel.fromJson(_result.data!); + return _value; } RequestOptions _setStreamType(RequestOptions requestOptions) { diff --git a/lib/features/blog_post_create/services/blog_service.g.dart b/lib/features/blog_post_create/services/blog_service.g.dart index eef2fc97..71ca2119 100644 --- a/lib/features/blog_post_create/services/blog_service.g.dart +++ b/lib/features/blog_post_create/services/blog_service.g.dart @@ -6,7 +6,7 @@ part of 'blog_service.dart'; // RetrofitGenerator // ************************************************************************** -// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers +// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element class _BlogService implements BlogService { _BlogService( @@ -42,8 +42,8 @@ class _BlogService implements BlogService { _dio.options.baseUrl, baseUrl, )))); - final value = BlogPostCreateCredentialsModel.fromJson(_result.data!); - return value; + final _value = BlogPostCreateCredentialsModel.fromJson(_result.data!); + return _value; } RequestOptions _setStreamType(RequestOptions requestOptions) { diff --git a/lib/features/chat/models/chat_message_model.dart b/lib/features/chat/models/chat_message_model.dart index 220df3bf..00e17f59 100644 --- a/lib/features/chat/models/chat_message_model.dart +++ b/lib/features/chat/models/chat_message_model.dart @@ -9,7 +9,7 @@ class ChatMessageModel with _$ChatMessageModel { const factory ChatMessageModel({ required int id, required String data, - @JsonKey(name: 'media_data') required List mediaData, + @JsonKey(name: 'media_data') required List? mediaData, @JsonKey(name: 'author_id') required int authorId, @JsonKey(name: 'updated_at') required String updatedAt, }) = _ChatMessageModel; diff --git a/lib/features/chat/models/chat_message_model.freezed.dart b/lib/features/chat/models/chat_message_model.freezed.dart index 61856085..76a91cbc 100644 --- a/lib/features/chat/models/chat_message_model.freezed.dart +++ b/lib/features/chat/models/chat_message_model.freezed.dart @@ -23,7 +23,7 @@ mixin _$ChatMessageModel { int get id => throw _privateConstructorUsedError; String get data => throw _privateConstructorUsedError; @JsonKey(name: 'media_data') - List get mediaData => throw _privateConstructorUsedError; + List? get mediaData => throw _privateConstructorUsedError; @JsonKey(name: 'author_id') int get authorId => throw _privateConstructorUsedError; @JsonKey(name: 'updated_at') @@ -44,7 +44,7 @@ abstract class $ChatMessageModelCopyWith<$Res> { $Res call( {int id, String data, - @JsonKey(name: 'media_data') List mediaData, + @JsonKey(name: 'media_data') List? mediaData, @JsonKey(name: 'author_id') int authorId, @JsonKey(name: 'updated_at') String updatedAt}); } @@ -64,7 +64,7 @@ class _$ChatMessageModelCopyWithImpl<$Res, $Val extends ChatMessageModel> $Res call({ Object? id = null, Object? data = null, - Object? mediaData = null, + Object? mediaData = freezed, Object? authorId = null, Object? updatedAt = null, }) { @@ -77,10 +77,10 @@ class _$ChatMessageModelCopyWithImpl<$Res, $Val extends ChatMessageModel> ? _value.data : data // ignore: cast_nullable_to_non_nullable as String, - mediaData: null == mediaData + mediaData: freezed == mediaData ? _value.mediaData : mediaData // ignore: cast_nullable_to_non_nullable - as List, + as List?, authorId: null == authorId ? _value.authorId : authorId // ignore: cast_nullable_to_non_nullable @@ -104,7 +104,7 @@ abstract class _$$ChatMessageModelImplCopyWith<$Res> $Res call( {int id, String data, - @JsonKey(name: 'media_data') List mediaData, + @JsonKey(name: 'media_data') List? mediaData, @JsonKey(name: 'author_id') int authorId, @JsonKey(name: 'updated_at') String updatedAt}); } @@ -122,7 +122,7 @@ class __$$ChatMessageModelImplCopyWithImpl<$Res> $Res call({ Object? id = null, Object? data = null, - Object? mediaData = null, + Object? mediaData = freezed, Object? authorId = null, Object? updatedAt = null, }) { @@ -135,10 +135,10 @@ class __$$ChatMessageModelImplCopyWithImpl<$Res> ? _value.data : data // ignore: cast_nullable_to_non_nullable as String, - mediaData: null == mediaData + mediaData: freezed == mediaData ? _value._mediaData : mediaData // ignore: cast_nullable_to_non_nullable - as List, + as List?, authorId: null == authorId ? _value.authorId : authorId // ignore: cast_nullable_to_non_nullable @@ -157,7 +157,7 @@ class _$ChatMessageModelImpl implements _ChatMessageModel { const _$ChatMessageModelImpl( {required this.id, required this.data, - @JsonKey(name: 'media_data') required final List mediaData, + @JsonKey(name: 'media_data') required final List? mediaData, @JsonKey(name: 'author_id') required this.authorId, @JsonKey(name: 'updated_at') required this.updatedAt}) : _mediaData = mediaData; @@ -169,13 +169,15 @@ class _$ChatMessageModelImpl implements _ChatMessageModel { final int id; @override final String data; - final List _mediaData; + final List? _mediaData; @override @JsonKey(name: 'media_data') - List get mediaData { + List? get mediaData { + final value = _mediaData; + if (value == null) return null; if (_mediaData is EqualUnmodifiableListView) return _mediaData; // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_mediaData); + return EqualUnmodifiableListView(value); } @override @@ -229,7 +231,7 @@ abstract class _ChatMessageModel implements ChatMessageModel { const factory _ChatMessageModel( {required final int id, required final String data, - @JsonKey(name: 'media_data') required final List mediaData, + @JsonKey(name: 'media_data') required final List? mediaData, @JsonKey(name: 'author_id') required final int authorId, @JsonKey(name: 'updated_at') required final String updatedAt}) = _$ChatMessageModelImpl; @@ -243,7 +245,7 @@ abstract class _ChatMessageModel implements ChatMessageModel { String get data; @override @JsonKey(name: 'media_data') - List get mediaData; + List? get mediaData; @override @JsonKey(name: 'author_id') int get authorId; diff --git a/lib/features/chat/models/chat_message_model.g.dart b/lib/features/chat/models/chat_message_model.g.dart index 8b28b749..3a8d1827 100644 --- a/lib/features/chat/models/chat_message_model.g.dart +++ b/lib/features/chat/models/chat_message_model.g.dart @@ -11,7 +11,7 @@ _$ChatMessageModelImpl _$$ChatMessageModelImplFromJson( _$ChatMessageModelImpl( id: (json['id'] as num).toInt(), data: json['data'] as String, - mediaData: json['media_data'] as List, + mediaData: json['media_data'] as List?, authorId: (json['author_id'] as num).toInt(), updatedAt: json['updated_at'] as String, ); diff --git a/lib/features/chat/models/chat_messages_model.dart b/lib/features/chat/models/chat_messages_model.dart new file mode 100644 index 00000000..fbf6fc05 --- /dev/null +++ b/lib/features/chat/models/chat_messages_model.dart @@ -0,0 +1,16 @@ +import 'package:eatvio_app/features/chat/models/chat_message_model.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'chat_messages_model.freezed.dart'; + +part 'chat_messages_model.g.dart'; + +@freezed +class ChatMessagesModel with _$ChatMessagesModel { + const factory ChatMessagesModel({ + @JsonKey(name: 'data') + required List messagesList, + }) = _ChatMessagesModel; + + factory ChatMessagesModel.fromJson(Map json) => _$ChatMessagesModelFromJson(json); +} diff --git a/lib/features/chat/models/chat_messages_model.freezed.dart b/lib/features/chat/models/chat_messages_model.freezed.dart new file mode 100644 index 00000000..594498a7 --- /dev/null +++ b/lib/features/chat/models/chat_messages_model.freezed.dart @@ -0,0 +1,168 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'chat_messages_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +ChatMessagesModel _$ChatMessagesModelFromJson(Map json) { + return _ChatMessagesModel.fromJson(json); +} + +/// @nodoc +mixin _$ChatMessagesModel { + @JsonKey(name: 'data') + List get messagesList => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $ChatMessagesModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ChatMessagesModelCopyWith<$Res> { + factory $ChatMessagesModelCopyWith( + ChatMessagesModel value, $Res Function(ChatMessagesModel) then) = + _$ChatMessagesModelCopyWithImpl<$Res, ChatMessagesModel>; + @useResult + $Res call({@JsonKey(name: 'data') List messagesList}); +} + +/// @nodoc +class _$ChatMessagesModelCopyWithImpl<$Res, $Val extends ChatMessagesModel> + implements $ChatMessagesModelCopyWith<$Res> { + _$ChatMessagesModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? messagesList = null, + }) { + return _then(_value.copyWith( + messagesList: null == messagesList + ? _value.messagesList + : messagesList // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ChatMessagesModelImplCopyWith<$Res> + implements $ChatMessagesModelCopyWith<$Res> { + factory _$$ChatMessagesModelImplCopyWith(_$ChatMessagesModelImpl value, + $Res Function(_$ChatMessagesModelImpl) then) = + __$$ChatMessagesModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({@JsonKey(name: 'data') List messagesList}); +} + +/// @nodoc +class __$$ChatMessagesModelImplCopyWithImpl<$Res> + extends _$ChatMessagesModelCopyWithImpl<$Res, _$ChatMessagesModelImpl> + implements _$$ChatMessagesModelImplCopyWith<$Res> { + __$$ChatMessagesModelImplCopyWithImpl(_$ChatMessagesModelImpl _value, + $Res Function(_$ChatMessagesModelImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? messagesList = null, + }) { + return _then(_$ChatMessagesModelImpl( + messagesList: null == messagesList + ? _value._messagesList + : messagesList // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ChatMessagesModelImpl implements _ChatMessagesModel { + const _$ChatMessagesModelImpl( + {@JsonKey(name: 'data') + required final List messagesList}) + : _messagesList = messagesList; + + factory _$ChatMessagesModelImpl.fromJson(Map json) => + _$$ChatMessagesModelImplFromJson(json); + + final List _messagesList; + @override + @JsonKey(name: 'data') + List get messagesList { + if (_messagesList is EqualUnmodifiableListView) return _messagesList; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_messagesList); + } + + @override + String toString() { + return 'ChatMessagesModel(messagesList: $messagesList)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChatMessagesModelImpl && + const DeepCollectionEquality() + .equals(other._messagesList, _messagesList)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash( + runtimeType, const DeepCollectionEquality().hash(_messagesList)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ChatMessagesModelImplCopyWith<_$ChatMessagesModelImpl> get copyWith => + __$$ChatMessagesModelImplCopyWithImpl<_$ChatMessagesModelImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$ChatMessagesModelImplToJson( + this, + ); + } +} + +abstract class _ChatMessagesModel implements ChatMessagesModel { + const factory _ChatMessagesModel( + {@JsonKey(name: 'data') + required final List messagesList}) = + _$ChatMessagesModelImpl; + + factory _ChatMessagesModel.fromJson(Map json) = + _$ChatMessagesModelImpl.fromJson; + + @override + @JsonKey(name: 'data') + List get messagesList; + @override + @JsonKey(ignore: true) + _$$ChatMessagesModelImplCopyWith<_$ChatMessagesModelImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/features/chat/models/chat_messages_model.g.dart b/lib/features/chat/models/chat_messages_model.g.dart new file mode 100644 index 00000000..80f78746 --- /dev/null +++ b/lib/features/chat/models/chat_messages_model.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'chat_messages_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$ChatMessagesModelImpl _$$ChatMessagesModelImplFromJson( + Map json) => + _$ChatMessagesModelImpl( + messagesList: (json['data'] as List) + .map((e) => ChatMessageModel.fromJson(e as Map)) + .toList(), + ); + +Map _$$ChatMessagesModelImplToJson( + _$ChatMessagesModelImpl instance) => + { + 'data': instance.messagesList, + }; diff --git a/lib/features/chat/models/chat_room_model.dart b/lib/features/chat/models/chat_room_model.dart index 1fa5afe7..0196b49c 100644 --- a/lib/features/chat/models/chat_room_model.dart +++ b/lib/features/chat/models/chat_room_model.dart @@ -1,4 +1,3 @@ -import 'package:eatvio_app/features/chat/models/chat_message_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_settings_model.dart'; import 'package:eatvio_app/features/chat/models/chat_user_model.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -12,7 +11,6 @@ class ChatRoomModel with _$ChatRoomModel { const factory ChatRoomModel({ required String id, @JsonKey(name: 'chat_room_setting') required ChatRoomSettingsModel chatRoomSettings, - required List messages, required Map users, }) = _ChatRoomModel; diff --git a/lib/features/chat/models/chat_room_model.freezed.dart b/lib/features/chat/models/chat_room_model.freezed.dart index b8b4ce46..5a0b6e62 100644 --- a/lib/features/chat/models/chat_room_model.freezed.dart +++ b/lib/features/chat/models/chat_room_model.freezed.dart @@ -24,7 +24,6 @@ mixin _$ChatRoomModel { @JsonKey(name: 'chat_room_setting') ChatRoomSettingsModel get chatRoomSettings => throw _privateConstructorUsedError; - List get messages => throw _privateConstructorUsedError; Map get users => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @@ -43,7 +42,6 @@ abstract class $ChatRoomModelCopyWith<$Res> { {String id, @JsonKey(name: 'chat_room_setting') ChatRoomSettingsModel chatRoomSettings, - List messages, Map users}); $ChatRoomSettingsModelCopyWith<$Res> get chatRoomSettings; @@ -64,7 +62,6 @@ class _$ChatRoomModelCopyWithImpl<$Res, $Val extends ChatRoomModel> $Res call({ Object? id = null, Object? chatRoomSettings = null, - Object? messages = null, Object? users = null, }) { return _then(_value.copyWith( @@ -76,10 +73,6 @@ class _$ChatRoomModelCopyWithImpl<$Res, $Val extends ChatRoomModel> ? _value.chatRoomSettings : chatRoomSettings // ignore: cast_nullable_to_non_nullable as ChatRoomSettingsModel, - messages: null == messages - ? _value.messages - : messages // ignore: cast_nullable_to_non_nullable - as List, users: null == users ? _value.users : users // ignore: cast_nullable_to_non_nullable @@ -109,7 +102,6 @@ abstract class _$$ChatRoomModelImplCopyWith<$Res> {String id, @JsonKey(name: 'chat_room_setting') ChatRoomSettingsModel chatRoomSettings, - List messages, Map users}); @override @@ -129,7 +121,6 @@ class __$$ChatRoomModelImplCopyWithImpl<$Res> $Res call({ Object? id = null, Object? chatRoomSettings = null, - Object? messages = null, Object? users = null, }) { return _then(_$ChatRoomModelImpl( @@ -141,10 +132,6 @@ class __$$ChatRoomModelImplCopyWithImpl<$Res> ? _value.chatRoomSettings : chatRoomSettings // ignore: cast_nullable_to_non_nullable as ChatRoomSettingsModel, - messages: null == messages - ? _value._messages - : messages // ignore: cast_nullable_to_non_nullable - as List, users: null == users ? _value._users : users // ignore: cast_nullable_to_non_nullable @@ -159,10 +146,8 @@ class _$ChatRoomModelImpl implements _ChatRoomModel { const _$ChatRoomModelImpl( {required this.id, @JsonKey(name: 'chat_room_setting') required this.chatRoomSettings, - required final List messages, required final Map users}) - : _messages = messages, - _users = users; + : _users = users; factory _$ChatRoomModelImpl.fromJson(Map json) => _$$ChatRoomModelImplFromJson(json); @@ -172,14 +157,6 @@ class _$ChatRoomModelImpl implements _ChatRoomModel { @override @JsonKey(name: 'chat_room_setting') final ChatRoomSettingsModel chatRoomSettings; - final List _messages; - @override - List get messages { - if (_messages is EqualUnmodifiableListView) return _messages; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_messages); - } - final Map _users; @override Map get users { @@ -190,7 +167,7 @@ class _$ChatRoomModelImpl implements _ChatRoomModel { @override String toString() { - return 'ChatRoomModel(id: $id, chatRoomSettings: $chatRoomSettings, messages: $messages, users: $users)'; + return 'ChatRoomModel(id: $id, chatRoomSettings: $chatRoomSettings, users: $users)'; } @override @@ -201,17 +178,12 @@ class _$ChatRoomModelImpl implements _ChatRoomModel { (identical(other.id, id) || other.id == id) && (identical(other.chatRoomSettings, chatRoomSettings) || other.chatRoomSettings == chatRoomSettings) && - const DeepCollectionEquality().equals(other._messages, _messages) && const DeepCollectionEquality().equals(other._users, _users)); } @JsonKey(ignore: true) @override - int get hashCode => Object.hash( - runtimeType, - id, - chatRoomSettings, - const DeepCollectionEquality().hash(_messages), + int get hashCode => Object.hash(runtimeType, id, chatRoomSettings, const DeepCollectionEquality().hash(_users)); @JsonKey(ignore: true) @@ -233,7 +205,6 @@ abstract class _ChatRoomModel implements ChatRoomModel { {required final String id, @JsonKey(name: 'chat_room_setting') required final ChatRoomSettingsModel chatRoomSettings, - required final List messages, required final Map users}) = _$ChatRoomModelImpl; factory _ChatRoomModel.fromJson(Map json) = @@ -245,8 +216,6 @@ abstract class _ChatRoomModel implements ChatRoomModel { @JsonKey(name: 'chat_room_setting') ChatRoomSettingsModel get chatRoomSettings; @override - List get messages; - @override Map get users; @override @JsonKey(ignore: true) diff --git a/lib/features/chat/models/chat_room_model.g.dart b/lib/features/chat/models/chat_room_model.g.dart index 4ab38671..68d3195c 100644 --- a/lib/features/chat/models/chat_room_model.g.dart +++ b/lib/features/chat/models/chat_room_model.g.dart @@ -11,9 +11,6 @@ _$ChatRoomModelImpl _$$ChatRoomModelImplFromJson(Map json) => id: json['id'] as String, chatRoomSettings: ChatRoomSettingsModel.fromJson( json['chat_room_setting'] as Map), - messages: (json['messages'] as List) - .map((e) => ChatMessageModel.fromJson(e as Map)) - .toList(), users: (json['users'] as Map).map( (k, e) => MapEntry(k, ChatUserModel.fromJson(e as Map)), @@ -24,6 +21,5 @@ Map _$$ChatRoomModelImplToJson(_$ChatRoomModelImpl instance) => { 'id': instance.id, 'chat_room_setting': instance.chatRoomSettings, - 'messages': instance.messages, 'users': instance.users, }; diff --git a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart index f66069e2..aff8fa8f 100644 --- a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart +++ b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart @@ -1,20 +1,108 @@ +import 'dart:convert'; + +import 'package:dart_pusher_channels/dart_pusher_channels.dart'; +import 'package:easy_debounce/easy_debounce.dart'; +import 'package:eatvio_app/core/initialization_cubit/initialization_cubit.dart'; +import 'package:eatvio_app/core/initialization_cubit/initialization_state.dart'; +import 'package:eatvio_app/core/token_storage.dart'; +import 'package:eatvio_app/features/chat/models/chat_message_model.dart'; import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart'; import 'package:eatvio_app/features/chat/repositories/chat_repository.dart'; +import 'package:eatvio_app/locator_service.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class ChatRoomCubit extends Cubit { final ChatRepository chatRepository; + late final PusherChannelsClient client; + late final PrivateChannel privateChannel; + ChatRoomCubit({ required this.chatRepository, }) : super(ChatRoomState.loading()); initChat(String chatId) async { try { - final chatRoomModel = await chatRepository.getChatRoom(chatId); - emit(ChatRoomState.loaded(chatRoomModel: chatRoomModel)); + final chatRoom = await chatRepository.getChatRoom(chatId); + + final chatMessages = await chatRepository.getChatMessages(chatId); + + final initCubit = sl(); + + if (initCubit.state is InitializationStateSuccess) { + await subscribeToChatChannel(initCubit: initCubit, chatId: chatId); + } else { + await initCubit.runInitialization(); + await subscribeToChatChannel(initCubit: initCubit, chatId: chatId); + } + + emit(ChatRoomState.loaded( + chatRoom: chatRoom, + chatMessages: chatMessages, + isTyping: false, + )); } catch (e) { emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных')); } } + + Future subscribeToChatChannel({ + required InitializationCubit initCubit, + required String chatId, + }) async { + client = (initCubit.state as InitializationStateSuccess).client; + + privateChannel = await client.privateChannel( + 'private-direct-chat.$chatId', + authorizationDelegate: EndpointAuthorizableChannelTokenAuthorizationDelegate.forPrivateChannel( + authorizationEndpoint: Uri.parse('https://mobile-stage.eatvio.ru/broadcasting/auth'), + headers: { + 'Authorization': 'Bearer ${await TokenStorage.getTokenFromStorage()}', + }, + ), + ); + + privateChannel.subscribe(); + + privateChannel.bind('App\\Events\\ChatMessageUpdated').listen((event) { + List messagesList = [ + ChatMessageModel.fromJson(jsonDecode(event.data)['message']), + ...(state as ChatRoomStateLoaded).chatMessages.messagesList, + ]; + emit( + ChatRoomState.loaded( + chatRoom: (state as ChatRoomStateLoaded).chatRoom, + chatMessages: (state as ChatRoomStateLoaded).chatMessages.copyWith(messagesList: messagesList), + isTyping: (state as ChatRoomStateLoaded).isTyping, + ), + ); + }); + + privateChannel.bind('client-typing').listen((event) { + emit( + ChatRoomState.loaded( + chatRoom: (state as ChatRoomStateLoaded).chatRoom, + chatMessages: (state as ChatRoomStateLoaded).chatMessages, + isTyping: true, + ), + ); + EasyDebounce.debounce( + 'client-typing', + Duration(seconds: 3), + () => emit( + ChatRoomState.loaded( + chatRoom: (state as ChatRoomStateLoaded).chatRoom, + chatMessages: (state as ChatRoomStateLoaded).chatMessages, + isTyping: false, + ), + ), + ); + }); + } + + @override + Future close() async { + privateChannel.unsubscribe(); + super.close(); + } } diff --git a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart index 89184a63..dbf82382 100644 --- a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart +++ b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart @@ -1,3 +1,4 @@ +import 'package:eatvio_app/features/chat/models/chat_messages_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_model.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -10,7 +11,9 @@ abstract class ChatRoomState with _$ChatRoomState { const factory ChatRoomState.loading() = ChatRoomStateLoading; const factory ChatRoomState.loaded({ - required ChatRoomModel chatRoomModel, + required ChatRoomModel chatRoom, + required ChatMessagesModel chatMessages, + required bool isTyping, }) = ChatRoomStateLoaded; const factory ChatRoomState.error({ diff --git a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.freezed.dart b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.freezed.dart index 5bd9ae89..4831cccb 100644 --- a/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.freezed.dart +++ b/lib/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.freezed.dart @@ -20,7 +20,9 @@ mixin _$ChatRoomState { TResult when( TResult Function() $default, { required TResult Function() loading, - required TResult Function(ChatRoomModel chatRoomModel) loaded, + required TResult Function(ChatRoomModel chatRoom, + ChatMessagesModel chatMessages, bool isTyping) + loaded, required TResult Function(String errorMessage) error, }) => throw _privateConstructorUsedError; @@ -28,7 +30,9 @@ mixin _$ChatRoomState { TResult? whenOrNull( TResult? Function()? $default, { TResult? Function()? loading, - TResult? Function(ChatRoomModel chatRoomModel)? loaded, + TResult? Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult? Function(String errorMessage)? error, }) => throw _privateConstructorUsedError; @@ -36,7 +40,9 @@ mixin _$ChatRoomState { TResult maybeWhen( TResult Function()? $default, { TResult Function()? loading, - TResult Function(ChatRoomModel chatRoomModel)? loaded, + TResult Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult Function(String errorMessage)? error, required TResult orElse(), }) => @@ -126,7 +132,9 @@ class _$ChatRoomStateImpl implements _ChatRoomState { TResult when( TResult Function() $default, { required TResult Function() loading, - required TResult Function(ChatRoomModel chatRoomModel) loaded, + required TResult Function(ChatRoomModel chatRoom, + ChatMessagesModel chatMessages, bool isTyping) + loaded, required TResult Function(String errorMessage) error, }) { return $default(); @@ -137,7 +145,9 @@ class _$ChatRoomStateImpl implements _ChatRoomState { TResult? whenOrNull( TResult? Function()? $default, { TResult? Function()? loading, - TResult? Function(ChatRoomModel chatRoomModel)? loaded, + TResult? Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult? Function(String errorMessage)? error, }) { return $default?.call(); @@ -148,7 +158,9 @@ class _$ChatRoomStateImpl implements _ChatRoomState { TResult maybeWhen( TResult Function()? $default, { TResult Function()? loading, - TResult Function(ChatRoomModel chatRoomModel)? loaded, + TResult Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult Function(String errorMessage)? error, required TResult orElse(), }) { @@ -241,7 +253,9 @@ class _$ChatRoomStateLoadingImpl implements ChatRoomStateLoading { TResult when( TResult Function() $default, { required TResult Function() loading, - required TResult Function(ChatRoomModel chatRoomModel) loaded, + required TResult Function(ChatRoomModel chatRoom, + ChatMessagesModel chatMessages, bool isTyping) + loaded, required TResult Function(String errorMessage) error, }) { return loading(); @@ -252,7 +266,9 @@ class _$ChatRoomStateLoadingImpl implements ChatRoomStateLoading { TResult? whenOrNull( TResult? Function()? $default, { TResult? Function()? loading, - TResult? Function(ChatRoomModel chatRoomModel)? loaded, + TResult? Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult? Function(String errorMessage)? error, }) { return loading?.call(); @@ -263,7 +279,9 @@ class _$ChatRoomStateLoadingImpl implements ChatRoomStateLoading { TResult maybeWhen( TResult Function()? $default, { TResult Function()? loading, - TResult Function(ChatRoomModel chatRoomModel)? loaded, + TResult Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult Function(String errorMessage)? error, required TResult orElse(), }) { @@ -321,9 +339,11 @@ abstract class _$$ChatRoomStateLoadedImplCopyWith<$Res> { $Res Function(_$ChatRoomStateLoadedImpl) then) = __$$ChatRoomStateLoadedImplCopyWithImpl<$Res>; @useResult - $Res call({ChatRoomModel chatRoomModel}); + $Res call( + {ChatRoomModel chatRoom, ChatMessagesModel chatMessages, bool isTyping}); - $ChatRoomModelCopyWith<$Res> get chatRoomModel; + $ChatRoomModelCopyWith<$Res> get chatRoom; + $ChatMessagesModelCopyWith<$Res> get chatMessages; } /// @nodoc @@ -337,21 +357,39 @@ class __$$ChatRoomStateLoadedImplCopyWithImpl<$Res> @pragma('vm:prefer-inline') @override $Res call({ - Object? chatRoomModel = null, + Object? chatRoom = null, + Object? chatMessages = null, + Object? isTyping = null, }) { return _then(_$ChatRoomStateLoadedImpl( - chatRoomModel: null == chatRoomModel - ? _value.chatRoomModel - : chatRoomModel // ignore: cast_nullable_to_non_nullable + chatRoom: null == chatRoom + ? _value.chatRoom + : chatRoom // ignore: cast_nullable_to_non_nullable as ChatRoomModel, + chatMessages: null == chatMessages + ? _value.chatMessages + : chatMessages // ignore: cast_nullable_to_non_nullable + as ChatMessagesModel, + isTyping: null == isTyping + ? _value.isTyping + : isTyping // ignore: cast_nullable_to_non_nullable + as bool, )); } @override @pragma('vm:prefer-inline') - $ChatRoomModelCopyWith<$Res> get chatRoomModel { - return $ChatRoomModelCopyWith<$Res>(_value.chatRoomModel, (value) { - return _then(_value.copyWith(chatRoomModel: value)); + $ChatRoomModelCopyWith<$Res> get chatRoom { + return $ChatRoomModelCopyWith<$Res>(_value.chatRoom, (value) { + return _then(_value.copyWith(chatRoom: value)); + }); + } + + @override + @pragma('vm:prefer-inline') + $ChatMessagesModelCopyWith<$Res> get chatMessages { + return $ChatMessagesModelCopyWith<$Res>(_value.chatMessages, (value) { + return _then(_value.copyWith(chatMessages: value)); }); } } @@ -359,14 +397,21 @@ class __$$ChatRoomStateLoadedImplCopyWithImpl<$Res> /// @nodoc class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded { - const _$ChatRoomStateLoadedImpl({required this.chatRoomModel}); + const _$ChatRoomStateLoadedImpl( + {required this.chatRoom, + required this.chatMessages, + required this.isTyping}); @override - final ChatRoomModel chatRoomModel; + final ChatRoomModel chatRoom; + @override + final ChatMessagesModel chatMessages; + @override + final bool isTyping; @override String toString() { - return 'ChatRoomState.loaded(chatRoomModel: $chatRoomModel)'; + return 'ChatRoomState.loaded(chatRoom: $chatRoom, chatMessages: $chatMessages, isTyping: $isTyping)'; } @override @@ -374,12 +419,17 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded { return identical(this, other) || (other.runtimeType == runtimeType && other is _$ChatRoomStateLoadedImpl && - (identical(other.chatRoomModel, chatRoomModel) || - other.chatRoomModel == chatRoomModel)); + (identical(other.chatRoom, chatRoom) || + other.chatRoom == chatRoom) && + (identical(other.chatMessages, chatMessages) || + other.chatMessages == chatMessages) && + (identical(other.isTyping, isTyping) || + other.isTyping == isTyping)); } @override - int get hashCode => Object.hash(runtimeType, chatRoomModel); + int get hashCode => + Object.hash(runtimeType, chatRoom, chatMessages, isTyping); @JsonKey(ignore: true) @override @@ -393,10 +443,12 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded { TResult when( TResult Function() $default, { required TResult Function() loading, - required TResult Function(ChatRoomModel chatRoomModel) loaded, + required TResult Function(ChatRoomModel chatRoom, + ChatMessagesModel chatMessages, bool isTyping) + loaded, required TResult Function(String errorMessage) error, }) { - return loaded(chatRoomModel); + return loaded(chatRoom, chatMessages, isTyping); } @override @@ -404,10 +456,12 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded { TResult? whenOrNull( TResult? Function()? $default, { TResult? Function()? loading, - TResult? Function(ChatRoomModel chatRoomModel)? loaded, + TResult? Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult? Function(String errorMessage)? error, }) { - return loaded?.call(chatRoomModel); + return loaded?.call(chatRoom, chatMessages, isTyping); } @override @@ -415,12 +469,14 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded { TResult maybeWhen( TResult Function()? $default, { TResult Function()? loading, - TResult Function(ChatRoomModel chatRoomModel)? loaded, + TResult Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult Function(String errorMessage)? error, required TResult orElse(), }) { if (loaded != null) { - return loaded(chatRoomModel); + return loaded(chatRoom, chatMessages, isTyping); } return orElse(); } @@ -465,9 +521,13 @@ class _$ChatRoomStateLoadedImpl implements ChatRoomStateLoaded { abstract class ChatRoomStateLoaded implements ChatRoomState { const factory ChatRoomStateLoaded( - {required final ChatRoomModel chatRoomModel}) = _$ChatRoomStateLoadedImpl; + {required final ChatRoomModel chatRoom, + required final ChatMessagesModel chatMessages, + required final bool isTyping}) = _$ChatRoomStateLoadedImpl; - ChatRoomModel get chatRoomModel; + ChatRoomModel get chatRoom; + ChatMessagesModel get chatMessages; + bool get isTyping; @JsonKey(ignore: true) _$$ChatRoomStateLoadedImplCopyWith<_$ChatRoomStateLoadedImpl> get copyWith => throw _privateConstructorUsedError; @@ -541,7 +601,9 @@ class _$ChatRoomStateErrorImpl implements ChatRoomStateError { TResult when( TResult Function() $default, { required TResult Function() loading, - required TResult Function(ChatRoomModel chatRoomModel) loaded, + required TResult Function(ChatRoomModel chatRoom, + ChatMessagesModel chatMessages, bool isTyping) + loaded, required TResult Function(String errorMessage) error, }) { return error(errorMessage); @@ -552,7 +614,9 @@ class _$ChatRoomStateErrorImpl implements ChatRoomStateError { TResult? whenOrNull( TResult? Function()? $default, { TResult? Function()? loading, - TResult? Function(ChatRoomModel chatRoomModel)? loaded, + TResult? Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult? Function(String errorMessage)? error, }) { return error?.call(errorMessage); @@ -563,7 +627,9 @@ class _$ChatRoomStateErrorImpl implements ChatRoomStateError { TResult maybeWhen( TResult Function()? $default, { TResult Function()? loading, - TResult Function(ChatRoomModel chatRoomModel)? loaded, + TResult Function(ChatRoomModel chatRoom, ChatMessagesModel chatMessages, + bool isTyping)? + loaded, TResult Function(String errorMessage)? error, required TResult orElse(), }) { diff --git a/lib/features/chat/presentation/pages/chat_screen.dart b/lib/features/chat/presentation/pages/chat_screen.dart index 31f431ac..b25be66d 100644 --- a/lib/features/chat/presentation/pages/chat_screen.dart +++ b/lib/features/chat/presentation/pages/chat_screen.dart @@ -19,6 +19,8 @@ class ChatScreen extends StatefulWidget { } class _ChatScreenState extends State { + final scrollController = ScrollController(); + Widget build(BuildContext context) { return BlocProvider( create: (BuildContext context) => sl()..initChat(widget.chatId), @@ -33,7 +35,12 @@ class _ChatScreenState extends State { } else if (state is ChatRoomStateLoaded) { return _buildChat(context, state); } else if (state is ChatRoomStateError) { - return Center(child: Text(state.errorMessage)); + return Scaffold( + appBar: AppBar(), + body: Center( + child: Text(state.errorMessage), + ), + ); } else { return Scaffold( body: Center( @@ -46,6 +53,16 @@ class _ChatScreenState extends State { ); } + void setupScrollController(BuildContext context) { + scrollController.addListener(() { + if (scrollController.position.atEdge) { + if (scrollController.position.pixels != 0) { + context.read(); + } + } + }); + } + _buildChat(BuildContext context, ChatRoomStateLoaded state) { mediaQueryData = MediaQuery.of(context); return Scaffold( @@ -68,7 +85,7 @@ class _ChatScreenState extends State { shape: BoxShape.circle, ), child: Text( - state.chatRoomModel.users['to_chat_user']!.name.split(' ').first[0] + state.chatRoomModel.users['to_chat_user']!.name.split(' ')[1][0], + state.chatRoom.users['to_chat_user']!.name.split(' ').first[0] + state.chatRoom.users['to_chat_user']!.name.split(' ')[1][0], style: TextStyle( color: Color(0xFF7F9CF5), fontWeight: FontWeight.w400, @@ -77,11 +94,27 @@ class _ChatScreenState extends State { ), ), SizedBox(width: 16), - Text( - state.chatRoomModel.users['to_chat_user']!.name, - style: CustomTextStyles.titleSmallBold.copyWith( - color: PrimaryColors().blueGray800, - ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + state.chatRoom.users['to_chat_user']!.name, + style: CustomTextStyles.titleSmallBold.copyWith( + color: PrimaryColors().blueGray800, + ), + ), + AnimatedCrossFade( + firstChild: Text( + 'Печатает...', + style: CustomTextStyles.bodySmallMulishPrimary, + ), + firstCurve: Curves.easeIn, + secondCurve: Curves.easeOut, + secondChild: const SizedBox.shrink(), + crossFadeState: state.isTyping ? CrossFadeState.showFirst : CrossFadeState.showSecond, + duration: Duration(milliseconds: 150), + ), + ], ), ], ), @@ -95,6 +128,8 @@ class _ChatScreenState extends State { color: Color(0xFFF0F2F5), width: double.maxFinite, child: CustomScrollView( + physics: BouncingScrollPhysics(), + controller: scrollController, reverse: true, slivers: [ SliverPadding( @@ -102,12 +137,11 @@ class _ChatScreenState extends State { 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, + text: state.chatMessages.messagesList[index].data.trim(), + isCurrentUser: state.chatRoom.users['to_chat_user']!.id != state.chatMessages.messagesList[index].authorId, + mediaData: state.chatMessages.messagesList[index].mediaData ?? [], ), - childCount: state.chatRoomModel.messages.length, + childCount: state.chatMessages.messagesList.length, ), ), ), 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 1a8e34a8..4836f94a 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 @@ -80,7 +80,7 @@ class ChatEntryWidget extends StatelessWidget { ), SizedBox(height: 6.v), Text( - chatEntryObj.greetingText!, + chatEntryObj.greetingText!.trim(), style: CustomTextStyles.bodyMediumBluegray800, ), ], diff --git a/lib/features/chat/presentation/widgets/chat_bubble_widget.dart b/lib/features/chat/presentation/widgets/chat_bubble_widget.dart index 39a13253..6f9e9389 100644 --- a/lib/features/chat/presentation/widgets/chat_bubble_widget.dart +++ b/lib/features/chat/presentation/widgets/chat_bubble_widget.dart @@ -11,12 +11,12 @@ class ChatBubbleWidget extends StatelessWidget { super.key, required this.text, required this.isCurrentUser, - this.mediaData, + required this.mediaData, }); final String text; final bool isCurrentUser; - final List? mediaData; + final List mediaData; @override Widget build(BuildContext context) { @@ -32,23 +32,24 @@ class ChatBubbleWidget extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(12), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (mediaData != null) + if (mediaData.isNotEmpty) CustomScrollView( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), slivers: [ SliverList.separated( itemBuilder: (BuildContext context, int index) { - if (!mediaData![index].toString().contains('.png') && - !mediaData![index].toString().contains('.jpg') && - !mediaData![index].toString().contains('.jpeg')) { + if (!mediaData[index].toString().contains('.png') && + !mediaData[index].toString().contains('.jpg') && + !mediaData[index].toString().contains('.jpeg')) { return ListTile( contentPadding: EdgeInsets.zero, horizontalTitleGap: 8, onTap: () async { - if (!await launchUrl(Uri.parse(dotenv.env['STORAGE_URL']! + mediaData![index].toString()))) { - throw Exception('Could not launch ${mediaData![index].toString()}'); + if (!await launchUrl(Uri.parse(dotenv.env['STORAGE_URL']! + mediaData[index].toString()))) { + throw Exception('Could not launch ${mediaData[index].toString()}'); } }, leading: Icon( @@ -60,7 +61,7 @@ class ChatBubbleWidget extends StatelessWidget { color: Color(0xFF2F80ED), ), title: Text( - mediaData![index].toString().replaceAll('chat_files/', ''), + mediaData[index].toString().replaceAll('chat_files/', ''), maxLines: 2, style: TextStyle( color: Color(0xFF323F4B), @@ -74,29 +75,29 @@ class ChatBubbleWidget extends StatelessWidget { onTap: () { context.pushTransparentRoute( PhotoViewScreen( - imageUrls: mediaData!.map((e) => dotenv.env['STORAGE_URL']! + e.toString()).toList(), + imageUrls: mediaData.map((e) => dotenv.env['STORAGE_URL']! + e.toString()).toList(), index: index, ), ); }, child: Hero( - tag: dotenv.env['STORAGE_URL']! + '${mediaData![index]}', + tag: dotenv.env['STORAGE_URL']! + '${mediaData[index]}', transitionOnUserGestures: true, child: ClipRRect( borderRadius: BorderRadiusStyle.roundedBorder8, child: CachedNetworkImage( - imageUrl: dotenv.env['STORAGE_URL']! + '${mediaData![index]}', + imageUrl: dotenv.env['STORAGE_URL']! + '${mediaData[index]}', ), ), ), ); }, separatorBuilder: (BuildContext context, int index) => const SizedBox(height: 8), - itemCount: mediaData!.length, + itemCount: mediaData.length, ), ], ), - if (mediaData!.length > 0 && text.isNotEmpty) SizedBox(height: 8), + if (mediaData.length > 0 && text.isNotEmpty) SizedBox(height: 8), if (text.isNotEmpty) Text( text, diff --git a/lib/features/chat/repositories/chat_repository.dart b/lib/features/chat/repositories/chat_repository.dart index 137aa878..38383f23 100644 --- a/lib/features/chat/repositories/chat_repository.dart +++ b/lib/features/chat/repositories/chat_repository.dart @@ -1,3 +1,4 @@ +import 'package:eatvio_app/features/chat/models/chat_messages_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_model.dart'; import 'package:eatvio_app/features/chat/models/websocket_info_model.dart'; import 'package:eatvio_app/features/chat/services/chat_service.dart'; @@ -9,23 +10,30 @@ class ChatRepository { required this.chatService, }); - /// TODO use "dartz" package because need Either for error handling Future getChatRoom(String chatId) async { try { - return (await chatService.getChatRoomModel(chatId))['chatRoom']!; + return (await chatService.getChatRoom(chatId))['chatRoom']!; } catch (e) { print(e); - throw (e); + rethrow; + } + } + + Future getChatMessages(String chatId) async { + try { + return (await chatService.getChatMessages(chatId)); + } catch (e) { + print(e); + rethrow; } } - /// TODO use "dartz" package because need Either for error handling Future getWebsocket() async { try { return (await chatService.getWebsocket()); } catch (e) { print(e); - throw (e); + rethrow; } } } diff --git a/lib/features/chat/services/chat_service.dart b/lib/features/chat/services/chat_service.dart index 5b27ccf2..3dd4a123 100644 --- a/lib/features/chat/services/chat_service.dart +++ b/lib/features/chat/services/chat_service.dart @@ -1,3 +1,4 @@ +import 'package:eatvio_app/features/chat/models/chat_messages_model.dart'; import 'package:eatvio_app/features/chat/models/chat_room_model.dart'; import 'package:dio/dio.dart'; import 'package:eatvio_app/features/chat/models/websocket_info_model.dart'; @@ -10,7 +11,10 @@ abstract class ChatService { factory ChatService(Dio dio, {String baseUrl}) = _ChatService; @GET('/chat/show/{id}') - Future> getChatRoomModel(@Path() String id); + Future> getChatRoom(@Path() String id); + + @GET('/chat/show/{id}/messages') + Future getChatMessages(@Path() String id); @GET('/profile/ws/params') Future getWebsocket(); diff --git a/lib/features/chat/services/chat_service.g.dart b/lib/features/chat/services/chat_service.g.dart index db9fdea8..f4f04d1d 100644 --- a/lib/features/chat/services/chat_service.g.dart +++ b/lib/features/chat/services/chat_service.g.dart @@ -6,7 +6,7 @@ part of 'chat_service.dart'; // RetrofitGenerator // ************************************************************************** -// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers +// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element class _ChatService implements ChatService { _ChatService( @@ -19,7 +19,7 @@ class _ChatService implements ChatService { String? baseUrl; @override - Future> getChatRoomModel(String id) async { + Future> getChatRoom(String id) async { final _extra = {}; final queryParameters = {}; final _headers = {}; @@ -41,9 +41,36 @@ class _ChatService implements ChatService { _dio.options.baseUrl, baseUrl, )))); - var value = _result.data!.map((k, dynamic v) => + var _value = _result.data!.map((k, dynamic v) => MapEntry(k, ChatRoomModel.fromJson(v as Map))); - return value; + return _value; + } + + @override + Future getChatMessages(String id) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + const Map? _data = null; + final _result = await _dio + .fetch>(_setStreamType(Options( + method: 'GET', + headers: _headers, + extra: _extra, + ) + .compose( + _dio.options, + '/chat/show/${id}/messages', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls( + _dio.options.baseUrl, + baseUrl, + )))); + final _value = ChatMessagesModel.fromJson(_result.data!); + return _value; } @override @@ -69,8 +96,8 @@ class _ChatService implements ChatService { _dio.options.baseUrl, baseUrl, )))); - final value = WebsocketInfoModel.fromJson(_result.data!); - return value; + final _value = WebsocketInfoModel.fromJson(_result.data!); + return _value; } RequestOptions _setStreamType(RequestOptions requestOptions) { diff --git a/lib/features/feed/services/feed_service.g.dart b/lib/features/feed/services/feed_service.g.dart index 6184cfbf..39b15fb5 100644 --- a/lib/features/feed/services/feed_service.g.dart +++ b/lib/features/feed/services/feed_service.g.dart @@ -6,7 +6,7 @@ part of 'feed_service.dart'; // RetrofitGenerator // ************************************************************************** -// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers +// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element class _FeedService implements FeedService { _FeedService( @@ -41,11 +41,11 @@ class _FeedService implements FeedService { _dio.options.baseUrl, baseUrl, )))); - var value = _result.data! + var _value = _result.data! .map((dynamic i) => FeedBlogPostModel.fromJson(i as Map)) .toList(); - return value; + return _value; } RequestOptions _setStreamType(RequestOptions requestOptions) { diff --git a/lib/locator_service.dart b/lib/locator_service.dart index f2ebc20a..fb2637ec 100644 --- a/lib/locator_service.dart +++ b/lib/locator_service.dart @@ -16,7 +16,8 @@ final sl = GetIt.instance; Future init() async { // BLoC / Cubit - sl.registerFactory(() => InitializationCubit(chatRepository: sl())); + sl.registerLazySingleton(() => InitializationCubit(chatRepository: sl())); + sl.registerFactory(() => ChatRoomCubit(chatRepository: sl())); sl.registerFactory(() => FeedCubit(feedRepository: sl())); sl.registerFactory(() => BlogPostCubit(blogPostRepository: sl())); diff --git a/lib/main.dart b/lib/main.dart index 9d608f20..684e227e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -42,7 +42,7 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiBlocProvider( providers: [ - BlocProvider(create: (context) => InitializationCubit(chatRepository: sl())..runInitialization()), + BlocProvider(create: (context) => InitializationCubit(chatRepository: sl())), BlocProvider(create: (context) => ThemeBloc(ThemeState(themeType: PrefUtils().getThemeData()))), BlocProvider(create: (context) => sl()..loadFeedBlogPostList()), BlocProvider(create: (context) => MyProfileBloc(MyProfileState(myProfileModelObj: MyProfileModel()))..add(MyProfileInitialEvent())), diff --git a/lib/presentation/registration/app_navigation_screen/app_navigation_screen.dart b/lib/presentation/registration/app_navigation_screen/app_navigation_screen.dart index 29c5748b..cbf92f01 100644 --- a/lib/presentation/registration/app_navigation_screen/app_navigation_screen.dart +++ b/lib/presentation/registration/app_navigation_screen/app_navigation_screen.dart @@ -156,7 +156,6 @@ class _AppNavigationScreenState extends State { style: TextStyle( color: Color(0XFF000000), fontSize: 20.fSize, - fontFamily: 'Roboto', fontWeight: FontWeight.w400, ), ), @@ -173,7 +172,6 @@ class _AppNavigationScreenState extends State { style: TextStyle( color: Color(0XFF888888), fontSize: 16.fSize, - fontFamily: 'Roboto', fontWeight: FontWeight.w400, ), ), @@ -215,7 +213,6 @@ class _AppNavigationScreenState extends State { style: TextStyle( color: Color(0XFF000000), fontSize: 20.fSize, - fontFamily: 'Roboto', fontWeight: FontWeight.w400, ), ), diff --git a/lib/theme/theme_helper.dart b/lib/theme/theme_helper.dart index 8a5d5ed4..c912cb29 100644 --- a/lib/theme/theme_helper.dart +++ b/lib/theme/theme_helper.dart @@ -121,7 +121,7 @@ class TextThemes { bodySmall: TextStyle( color: appTheme.gray500, fontSize: 10.fSize, - fontFamily: 'Roboto', + fontFamily: 'Mulish', fontWeight: FontWeight.w400, ), labelLarge: TextStyle( diff --git a/pubspec.yaml b/pubspec.yaml index 49e9d729..256f8923 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,8 +64,10 @@ dependencies: # photo gallery viewer + dismissible page photo_view: ^0.15.0 dismissible_page: ^1.0.2 - #url launcher + # url launcher url_launcher: ^6.3.0 + # debounce + easy_debounce: ^2.0.3 dev_dependencies: build_runner: ^2.4.11