Merge pull request 'build' (#557) from main into test-flight

Reviewed-on: eatvio/eatvio_app#557
This commit is contained in:
mso7nueh
2025-07-11 11:49:36 +00:00
33 changed files with 203 additions and 1491 deletions

2
.gitignore vendored
View File

@@ -12,5 +12,7 @@
/android/app/.cxx
*.g.dart
*.freezed.dart
*.gr.dart
*.mocks.dart
android/build/
ios/XCBuildData/

File diff suppressed because one or more lines are too long

View File

@@ -388,7 +388,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 39;
CURRENT_PROJECT_VERSION = 52;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -538,7 +538,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 39;
CURRENT_PROJECT_VERSION = 52;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -576,7 +576,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 39;
CURRENT_PROJECT_VERSION = 52;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (

View File

@@ -21,7 +21,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>39</string>
<string>52</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>

View File

@@ -373,10 +373,10 @@ class AppRouter {
name: 'chatScreen',
builder: (context, state) {
final data = state.extra as Map<String, dynamic>;
final chatId = data['chatId'] as String;
final uuid = data['uuid'] as String;
final sendInitialMessage = data['sendInitialMessage'] as bool?;
return ChatScreen(
chatId: chatId,
uuid: uuid,
sendInitialMessage: sendInitialMessage,
);
},

View File

@@ -244,7 +244,6 @@ Future<void> init() async {
'accept': 'application/json',
'content-type': 'application/json',
},
validateStatus: (status) => status != null && status < 500,
),
)..interceptors.addAll(
[

View File

@@ -1,3 +1,5 @@
import 'dart:io';
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:flutter/cupertino.dart';
@@ -11,6 +13,10 @@ class PermissionHandler {
required Future<void> Function() onGranted,
required BuildContext context,
}) async {
if (Platform.isAndroid) {
await onGranted();
return;
}
final permissionState = await permission.request();
if (permissionState.isGranted) {
await onGranted();

View File

@@ -21,3 +21,25 @@ abstract class TokenStorage {
static Future<void> removeTokenInStorage() async => (await const FlutterSecureStorage().delete(key: 'token'));
}
abstract class SocketIdStorage {
static Future<bool> haveSocketIdInStorage() async {
try {
if (await const FlutterSecureStorage().read(key: 'socketId') == null) {
return false;
} else {
return true;
}
} catch (e) {
return false;
}
}
static Future<String?> getSocketIdFromStorage() async => await const FlutterSecureStorage().read(key: 'socketId');
static Future<void> saveSocketIdInStorage(String socketId) async {
await const FlutterSecureStorage().write(key: 'socketId', value: socketId);
}
static Future<void> removeSocketIdInStorage() async => (await const FlutterSecureStorage().delete(key: 'socketId'));
}

View File

@@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:developer';
import 'package:dart_pusher_channels/dart_pusher_channels.dart';
@@ -59,6 +60,24 @@ class WsManager {
),
);
String? extractSocketId(String? data) {
if (data == null) return null;
try {
final decoded = jsonDecode(data);
return decoded['socket_id'] as String?;
} catch (_) {
return null;
}
}
client?.eventStream.listen((event) async {
if (event.name == 'pusher:connection_established') {
final data = event.data;
final socketId = extractSocketId(data);
await SocketIdStorage.saveSocketIdInStorage(socketId!);
}
});
await client?.connect();
client = client;
@@ -77,9 +96,8 @@ class WsManager {
EasyDebounce.debounce(
'searchChatRoom',
const Duration(milliseconds: 300),
() => sl<ChatsCubit>().getChatRooms(),
() => sl<ChatsCubit>().getChatRooms(),
);
log(event.rootObject.toString());
});
_subscribe();
} catch (e, st) {

View File

@@ -79,6 +79,9 @@ class _AuthScreenState extends State<AuthScreen> {
@override
Widget build(BuildContext context) {
var shortestSide = MediaQuery.sizeOf(context).shortestSide;
final bool useMobileLayout = shortestSide < 600;
if (!useMobileLayout) isFocused = true;
final s = S.of(context);
FlutterNativeSplash.remove();
return BlocProvider<AuthCubit>(

View File

@@ -9,7 +9,7 @@ part 'chat_room_model.g.dart';
@freezed
abstract class ChatRoomModel with _$ChatRoomModel {
const factory ChatRoomModel({
required String id,
required String id,
@JsonKey(name: 'chat_room_setting') required ChatRoomSettingsModel chatRoomSettings,
required Users users,
@JsonKey(name: 'chosen_plan_id') required int? chosenPlanId,

View File

@@ -1,3 +1,4 @@
import 'package:eatvio_app/core/models/pagination_model.dart';
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@@ -8,29 +9,18 @@ part 'chat_room_pagination_model.g.dart';
@freezed
abstract class ChatRoomPaginationModel with _$ChatRoomPaginationModel {
const factory ChatRoomPaginationModel({
@JsonKey(name: "chatRooms") required ChatRooms chatRooms,
@JsonKey(name: "data") required List<ChatRoom> data,
@JsonKey(name: "number_of_unread_chat_rooms") required int unreadChatsCount,
required Meta meta,
}) = _ChatRoomPreviewModel;
factory ChatRoomPaginationModel.fromJson(Map<String, dynamic> json) => _$ChatRoomPaginationModelFromJson(json);
}
@freezed
abstract class ChatRooms with _$ChatRooms {
const factory ChatRooms({
@JsonKey(name: "data") required List<ChatRoom> data,
@JsonKey(name: "last_page") required int lastPage,
@JsonKey(name: "current_page") required int currentPage,
}) = _ChatRooms;
factory ChatRooms.fromJson(Map<String, dynamic> json) => _$ChatRoomsFromJson(json);
}
@freezed
abstract class ChatRoom with _$ChatRoom {
const factory ChatRoom({
@JsonKey(name: "id") required String id,
@JsonKey(name: "room_name") required String roomName,
@JsonKey(name: "last_message", fromJson: parseLastMessage) required ChatMessageModel? lastMessage,
@JsonKey(name: "users") required Users users,
@JsonKey(name: "unread_messages_count") required int unreadMessagesCount,

View File

@@ -6,11 +6,8 @@ part 'chat_room_settings_model.g.dart';
@freezed
abstract class ChatRoomSettingsModel with _$ChatRoomSettingsModel {
const factory ChatRoomSettingsModel({
required int id,
@JsonKey(name: 'room_name') required String roomName,
required String name,
required String state,
@JsonKey(name: 'access_level') required String accessLevel,
@JsonKey(name: 'updated_at') required String updatedAt,
}) = _ChatRoomSettingsModel;
factory ChatRoomSettingsModel.fromJson(Map<String, Object?> json) => _$ChatRoomSettingsModelFromJson(json);

View File

@@ -47,14 +47,14 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
_timer?.cancel();
}
Future<void> loadNextPage(String chatId) async {
Future<void> loadNextPage(String uuid) async {
if (currentPage < lastPage && !isLoading) {
isLoading = true;
emit((state as ChatRoomStateLoaded).copyWith(isLoading: isLoading));
try {
final chatMessages = await chatRepository.getChatMessages(chatId, currentPage + 1);
final chatMessages = await chatRepository.getChatMessages(uuid, currentPage + 1);
isLoading = false;
emit(
@@ -89,17 +89,19 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
}
}
Future<void> initChat(String chatId, {bool sendInitialMessage = false}) async {
Future<void> initChat(
String uuid, {
bool sendInitialMessage = false,
}) async {
try {
final chatRoom = await chatRepository.getChatRoom(chatId);
final chatRoom = await chatRepository.getChatRoom(uuid);
ChosenPlanModel? chosenPlan;
if (chatRoom.chosenPlanId != null) {
chosenPlan = await chatRepository.getChosenPlan(id: chatRoom.chosenPlanId!);
}
final chatMessages = await chatRepository.getChatMessages(chatId, currentPage);
final chatMessages = await chatRepository.getChatMessages(uuid, currentPage);
lastPage = chatMessages.meta.lastPage;
await _subscribeToChatChannel(chatId: chatId);
await _subscribeToChatChannel(uuid: uuid, chatId: chatRoom.id);
emit(
ChatRoomState.loaded(
chatRoom: chatRoom.copyWith(chosenPlan: chosenPlan),
@@ -158,14 +160,14 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
}
}
Future<void> _subscribeToChatChannel({required String chatId}) async {
Future<void> _subscribeToChatChannel({required String uuid, required String chatId}) async {
final client = wsManager.client;
if (client == null) return;
await wsManager.initPrivateDirectChatChannel(chatId);
wsManager.subscribeDirectChatChannel();
messagesSubscription = wsManager.directChatStream?.listen((event) {
AudioPlayer().play((AssetSource('audio/recive_message.wav')));
final message = ChatMessageModel.fromJson(jsonDecode(event.data)['message']);
final message = ChatMessageModel.fromJson(jsonDecode(event.data));
List<ChatMessageModel> messagesList = [message, ...(state as ChatRoomStateLoaded).chatMessages];
chatRepository.emitNewMessageToChats(message);
emit((state as ChatRoomStateLoaded).copyWith(chatMessages: messagesList, isLoading: isLoading));
@@ -179,7 +181,15 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
typingSubscription = wsManager.clientTypingStream?.listen((event) {
emit((state as ChatRoomStateLoaded).copyWith(isTyping: true, isLoading: isLoading));
EasyDebounce.debounce(
'client-typing', const Duration(seconds: 3), () => emit((state as ChatRoomStateLoaded).copyWith(isTyping: false, isLoading: isLoading)));
'client-typing',
const Duration(seconds: 3),
() => emit(
(state as ChatRoomStateLoaded).copyWith(
isTyping: false,
isLoading: isLoading,
),
),
);
});
}
@@ -189,12 +199,30 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
required String userSlug,
}) async {
try {
final compressedFiles = files != null ? await ImageCompressUtility.compressFilesList(List<File>.from(files)) : null;
AudioPlayer().play((AssetSource('audio/send_message.wav')));
emit(
(state as ChatRoomStateLoaded).copyWith(
chatMessages: [
ChatMessageModel(
id: 1,
data: data ?? '',
mediaData: compressedFiles,
authorId: 1,
updatedAt: DateTime.now(),
isRead: true,
isCurrentUserAuthor: true,
roomId: '',
),
...(state as ChatRoomStateLoaded).chatMessages,
],
),
);
await chatRepository.sendMessage(
data: data,
files: files != null ? await ImageCompressUtility.compressFilesList(List<File>.from(files)) : null,
files: compressedFiles,
slug: userSlug,
);
AudioPlayer().play((AssetSource('audio/send_message.wav')));
return true;
} catch (e, st) {
log(e.toString(), stackTrace: st);

View File

@@ -21,7 +21,7 @@ class ChatsCubit extends Cubit<ChatsState> {
required this.chatRepository,
required this.wsManager,
required this.profileRepository,
}) : super(ChatsState()) {
}) : super(ChatsState()) {
newLastMessageSubscription = chatRepository.newUserMessagesStream.listen((message) {
_setNewLastMessage(message);
});
@@ -29,6 +29,7 @@ class ChatsCubit extends Cubit<ChatsState> {
String? _query;
int page = 1;
late int lastPage;
Future<void> connectToWebSocket() async {
await newIncomingMessagesSubscription?.cancel();
newIncomingMessagesSubscription = wsManager.newMessagesStream?.listen((event) {
@@ -43,10 +44,10 @@ class ChatsCubit extends Cubit<ChatsState> {
try {
final chatRoomsPaginationModel = await chatRepository.getChatRooms(query: query);
final unreadChats = chatRoomsPaginationModel.unreadChatsCount;
lastPage = chatRoomsPaginationModel.chatRooms.lastPage + 1;
lastPage = chatRoomsPaginationModel.meta.lastPage + 1;
emit(
state.copyWith(
chatRooms: chatRoomsPaginationModel.chatRooms.data,
chatRooms: chatRoomsPaginationModel.data,
chatsWithUnreadMessagesCount: unreadChats,
state: BaseState.success,
),
@@ -65,10 +66,10 @@ class ChatsCubit extends Cubit<ChatsState> {
try {
final chatRoomsPaginationModel = await chatRepository.getChatRooms(query: query);
final unreadChats = chatRoomsPaginationModel.unreadChatsCount;
lastPage = chatRoomsPaginationModel.chatRooms.lastPage + 1;
lastPage = chatRoomsPaginationModel.meta.lastPage + 1;
emit(
state.copyWith(
chatRooms: chatRoomsPaginationModel.chatRooms.data,
chatRooms: chatRoomsPaginationModel.data,
chatsWithUnreadMessagesCount: unreadChats,
state: BaseState.success,
),
@@ -90,7 +91,7 @@ class ChatsCubit extends Cubit<ChatsState> {
final unreadChats = chatRoomsPaginationModel.unreadChatsCount;
emit(
state.copyWith(
chatRooms: [...state.chatRooms, ...chatRoomsPaginationModel.chatRooms.data],
chatRooms: [...state.chatRooms, ...chatRoomsPaginationModel.data],
chatsWithUnreadMessagesCount: unreadChats,
state: BaseState.success,
isLoadingMoreChats: false,

View File

@@ -32,10 +32,10 @@ import 'package:intl/intl.dart';
import 'package:visibility_detector/visibility_detector.dart';
class ChatScreen extends StatefulWidget {
final String chatId;
final String uuid;
final bool? sendInitialMessage;
const ChatScreen({required this.chatId, super.key, required this.sendInitialMessage});
const ChatScreen({required this.uuid, super.key, required this.sendInitialMessage});
@override
State<ChatScreen> createState() => _ChatScreenState();
@@ -64,14 +64,14 @@ class _ChatScreenState extends State<ChatScreen> {
void initState() {
super.initState();
scrollController.addListener(_onScroll);
chatRoomCubit.initChat(widget.chatId, sendInitialMessage: widget.sendInitialMessage ?? false);
chatRoomCubit.initChat(widget.uuid, sendInitialMessage: widget.sendInitialMessage ?? false);
chatRoomCubit.setTimer();
_listener = AppLifecycleListener(onHide: _onHide, onResume: _onResume);
}
void _onScroll() {
if (scrollController.offset >= scrollController.position.maxScrollExtent && !scrollController.position.outOfRange) {
chatRoomCubit.loadNextPage(widget.chatId);
chatRoomCubit.loadNextPage(widget.uuid);
}
}
@@ -93,7 +93,7 @@ class _ChatScreenState extends State<ChatScreen> {
if (state is ChatRoomStateLoaded) {
return _buildChat(context, state);
} else if (state is ChatRoomStateError) {
return Scaffold(appBar: AppBar(), body: DataErrorWidget(onReload: () => chatRoomCubit.initChat(widget.chatId)));
return Scaffold(appBar: AppBar(), body: DataErrorWidget(onReload: () => chatRoomCubit.initChat(widget.uuid)));
} else {
return const Scaffold(body: Loader());
}

View File

@@ -145,7 +145,7 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
AppRouter.navigatorKey.currentContext?.pushReplacementNamed(
'chatScreen',
extra: {
'chatId': chatIdOrError,
'uuid': chatIdOrError,
},
);
}
@@ -186,7 +186,7 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
AppRouter.navigatorKey.currentContext?.pushReplacementNamed(
'chatScreen',
extra: {
'chatId': chatIdOrError,
'uuid': chatIdOrError,
},
);
}
@@ -214,7 +214,7 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
AppRouter.navigatorKey.currentContext?.pushReplacementNamed(
'chatScreen',
extra: {
'chatId': chatIdOrError,
'uuid': chatIdOrError,
},
);
}
@@ -264,7 +264,7 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
AppRouter.navigatorKey.currentContext?.pushReplacementNamed(
'chatScreen',
extra: {
'chatId': chatIdOrError,
'uuid': chatIdOrError,
},
);
}

View File

@@ -1,3 +1,5 @@
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:dismissible_page/dismissible_page.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
@@ -59,8 +61,9 @@ class ChatBubbleWidget extends StatelessWidget {
),
),
child: Padding(
padding:
mediaData.isNotEmpty ? const EdgeInsets.all(8) : EdgeInsets.only(top: 8, bottom: 8, left: isCurrentUser ? 16 : 8, right: isCurrentUser ? 8 : 16),
padding: mediaData.isNotEmpty
? const EdgeInsets.all(8)
: EdgeInsets.only(top: 8, bottom: 8, left: isCurrentUser ? 16 : 8, right: isCurrentUser ? 8 : 16),
child: Column(
crossAxisAlignment: isCurrentUser ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: [
@@ -86,17 +89,17 @@ class ChatBubbleWidget extends StatelessWidget {
},
leading: const Icon(
Icons.file_copy_outlined,
color: Colors.white,
color: Colors.black,
),
trailing: const Icon(
Icons.download_outlined,
color: Colors.white,
color: Colors.black,
),
title: Text(
mediaData[index].toString().replaceAll('chat_files/', ''),
maxLines: 2,
style: const TextStyle(
color: Colors.white,
color: Colors.black,
fontSize: 12,
overflow: TextOverflow.ellipsis,
),
@@ -109,6 +112,7 @@ class ChatBubbleWidget extends StatelessWidget {
PhotoViewScreen(
imageUrls: mediaData.map((e) => '$e').toList(),
index: index,
isLocal: mediaData[index] is File ? true : false,
),
);
},
@@ -117,9 +121,11 @@ class ChatBubbleWidget extends StatelessWidget {
transitionOnUserGestures: true,
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: CachedNetworkImage(
imageUrl: '${mediaData[index]}',
),
child: mediaData[index] is File
? Image.file(mediaData[index])
: CachedNetworkImage(
imageUrl: '${mediaData[index]}',
),
),
),
);

View File

@@ -24,7 +24,7 @@ class _ChatEntryWidgetState extends State<ChatEntryWidget> {
onTap: () => GoRouter.of(context).pushNamed(
'chatScreen',
extra: {
'chatId': widget.chatRoom.id.toString(),
'uuid': widget.chatRoom.id.toString(),
},
),
child: Container(

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:dio/dio.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/models/chat_messages_model.dart';
import 'package:eatvio_app/features/chat/models/chat_room_model.dart';
@@ -47,10 +48,11 @@ class ChatRepository {
}
}
await chatService.sendMessageByUserSlug(
userSlug: slug,
await chatService.sendMessage(
slug: slug,
data: data,
mediaData: multipartFiles.isEmpty ? null : multipartFiles,
socketId: (await SocketIdStorage.getSocketIdFromStorage())!,
);
} catch (e, st) {
log(e.toString(), stackTrace: st);
@@ -58,9 +60,9 @@ class ChatRepository {
}
}
Future<ChatRoomModel> getChatRoom(String chatId) async {
Future<ChatRoomModel> getChatRoom(String uuid) async {
try {
return (await chatService.getChatRoom(id: chatId))['chatRoom']!;
return (await chatService.getChatRoom(uuid: uuid));
} catch (e) {
rethrow;
}
@@ -74,9 +76,9 @@ class ChatRepository {
}
}
Future<ChatMessagesModel> getChatMessages(String chatId, int page) async {
Future<ChatMessagesModel> getChatMessages(String id, int page) async {
try {
return (await chatService.getChatMessages(id: chatId, page: page));
return (await chatService.getChatMessages(id: id, page: page));
} catch (e) {
rethrow;
}
@@ -90,9 +92,9 @@ class ChatRepository {
}
}
Future<void> markMessagesAsRead(String chatId, List<int> messageIds) async {
Future<void> markMessagesAsRead(String id, List<int> messageIds) async {
try {
await chatService.markMessagesAsRead(id: chatId, body: {'messages_ids': messageIds});
await chatService.markMessagesAsRead(id: id, body: {'messages_ids': messageIds});
} catch (e) {
rethrow;
}

View File

@@ -19,15 +19,16 @@ abstract class ChatService {
@Query('find') String? query,
});
@GET('/api/chat/show/{id}')
Future<Map<String, ChatRoomModel>> getChatRoom({
@Path() required String id,
@GET('/api/chat/show/{uuid}')
Future<ChatRoomModel> getChatRoom({
@Path() required String uuid,
});
@POST('/api/v2/chat/message/send/{id}')
@POST('/api/chat/message/send/{slug}')
@MultiPart()
Future<void> sendMessage({
@Path() required String id,
@Header('X-Socket-ID') required String socketId,
@Path() required String slug,
@Part() String? data,
@Part(name: 'media_data[]', contentType: 'multipart/form-data') List<MultipartFile>? mediaData,
});
@@ -85,12 +86,4 @@ abstract class ChatService {
Future<HttpResponse> getChatByUserSlug({
@Path() required String slug,
});
@POST('/api/v2/chat/message/send/{userSlug}')
@MultiPart()
Future<void> sendMessageByUserSlug({
@Path() required String userSlug,
@Part() String? data,
@Part(name: 'media_data[]', contentType: 'multipart/form-data') List<MultipartFile>? mediaData,
});
}

View File

@@ -1,784 +0,0 @@
// dart format width=80
// 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 'consultant_review_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$ConsultantReviewModel {
String get planName;
int get planDuration;
int get currentPlanDay;
ConsultantComments get consultantComments;
/// Create a copy of ConsultantReviewModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$ConsultantReviewModelCopyWith<ConsultantReviewModel> get copyWith =>
_$ConsultantReviewModelCopyWithImpl<ConsultantReviewModel>(
this as ConsultantReviewModel, _$identity);
/// Serializes this ConsultantReviewModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is ConsultantReviewModel &&
(identical(other.planName, planName) ||
other.planName == planName) &&
(identical(other.planDuration, planDuration) ||
other.planDuration == planDuration) &&
(identical(other.currentPlanDay, currentPlanDay) ||
other.currentPlanDay == currentPlanDay) &&
(identical(other.consultantComments, consultantComments) ||
other.consultantComments == consultantComments));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType, planName, planDuration, currentPlanDay, consultantComments);
@override
String toString() {
return 'ConsultantReviewModel(planName: $planName, planDuration: $planDuration, currentPlanDay: $currentPlanDay, consultantComments: $consultantComments)';
}
}
/// @nodoc
abstract mixin class $ConsultantReviewModelCopyWith<$Res> {
factory $ConsultantReviewModelCopyWith(ConsultantReviewModel value,
$Res Function(ConsultantReviewModel) _then) =
_$ConsultantReviewModelCopyWithImpl;
@useResult
$Res call(
{String planName,
int planDuration,
int currentPlanDay,
ConsultantComments consultantComments});
$ConsultantCommentsCopyWith<$Res> get consultantComments;
}
/// @nodoc
class _$ConsultantReviewModelCopyWithImpl<$Res>
implements $ConsultantReviewModelCopyWith<$Res> {
_$ConsultantReviewModelCopyWithImpl(this._self, this._then);
final ConsultantReviewModel _self;
final $Res Function(ConsultantReviewModel) _then;
/// Create a copy of ConsultantReviewModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? planName = null,
Object? planDuration = null,
Object? currentPlanDay = null,
Object? consultantComments = null,
}) {
return _then(_self.copyWith(
planName: null == planName
? _self.planName
: planName // ignore: cast_nullable_to_non_nullable
as String,
planDuration: null == planDuration
? _self.planDuration
: planDuration // ignore: cast_nullable_to_non_nullable
as int,
currentPlanDay: null == currentPlanDay
? _self.currentPlanDay
: currentPlanDay // ignore: cast_nullable_to_non_nullable
as int,
consultantComments: null == consultantComments
? _self.consultantComments
: consultantComments // ignore: cast_nullable_to_non_nullable
as ConsultantComments,
));
}
/// Create a copy of ConsultantReviewModel
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$ConsultantCommentsCopyWith<$Res> get consultantComments {
return $ConsultantCommentsCopyWith<$Res>(_self.consultantComments, (value) {
return _then(_self.copyWith(consultantComments: value));
});
}
}
/// @nodoc
@JsonSerializable()
class _ConsultantReviewModel implements ConsultantReviewModel {
_ConsultantReviewModel(
{required this.planName,
required this.planDuration,
required this.currentPlanDay,
required this.consultantComments});
factory _ConsultantReviewModel.fromJson(Map<String, dynamic> json) =>
_$ConsultantReviewModelFromJson(json);
@override
final String planName;
@override
final int planDuration;
@override
final int currentPlanDay;
@override
final ConsultantComments consultantComments;
/// Create a copy of ConsultantReviewModel
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$ConsultantReviewModelCopyWith<_ConsultantReviewModel> get copyWith =>
__$ConsultantReviewModelCopyWithImpl<_ConsultantReviewModel>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$ConsultantReviewModelToJson(
this,
);
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _ConsultantReviewModel &&
(identical(other.planName, planName) ||
other.planName == planName) &&
(identical(other.planDuration, planDuration) ||
other.planDuration == planDuration) &&
(identical(other.currentPlanDay, currentPlanDay) ||
other.currentPlanDay == currentPlanDay) &&
(identical(other.consultantComments, consultantComments) ||
other.consultantComments == consultantComments));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType, planName, planDuration, currentPlanDay, consultantComments);
@override
String toString() {
return 'ConsultantReviewModel(planName: $planName, planDuration: $planDuration, currentPlanDay: $currentPlanDay, consultantComments: $consultantComments)';
}
}
/// @nodoc
abstract mixin class _$ConsultantReviewModelCopyWith<$Res>
implements $ConsultantReviewModelCopyWith<$Res> {
factory _$ConsultantReviewModelCopyWith(_ConsultantReviewModel value,
$Res Function(_ConsultantReviewModel) _then) =
__$ConsultantReviewModelCopyWithImpl;
@override
@useResult
$Res call(
{String planName,
int planDuration,
int currentPlanDay,
ConsultantComments consultantComments});
@override
$ConsultantCommentsCopyWith<$Res> get consultantComments;
}
/// @nodoc
class __$ConsultantReviewModelCopyWithImpl<$Res>
implements _$ConsultantReviewModelCopyWith<$Res> {
__$ConsultantReviewModelCopyWithImpl(this._self, this._then);
final _ConsultantReviewModel _self;
final $Res Function(_ConsultantReviewModel) _then;
/// Create a copy of ConsultantReviewModel
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$Res call({
Object? planName = null,
Object? planDuration = null,
Object? currentPlanDay = null,
Object? consultantComments = null,
}) {
return _then(_ConsultantReviewModel(
planName: null == planName
? _self.planName
: planName // ignore: cast_nullable_to_non_nullable
as String,
planDuration: null == planDuration
? _self.planDuration
: planDuration // ignore: cast_nullable_to_non_nullable
as int,
currentPlanDay: null == currentPlanDay
? _self.currentPlanDay
: currentPlanDay // ignore: cast_nullable_to_non_nullable
as int,
consultantComments: null == consultantComments
? _self.consultantComments
: consultantComments // ignore: cast_nullable_to_non_nullable
as ConsultantComments,
));
}
/// Create a copy of ConsultantReviewModel
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$ConsultantCommentsCopyWith<$Res> get consultantComments {
return $ConsultantCommentsCopyWith<$Res>(_self.consultantComments, (value) {
return _then(_self.copyWith(consultantComments: value));
});
}
}
/// @nodoc
mixin _$ConsultantComments {
String? get dayComment;
List<MealComment> get mealsComments;
List<PortionComment> get portionsComments;
/// Create a copy of ConsultantComments
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$ConsultantCommentsCopyWith<ConsultantComments> get copyWith =>
_$ConsultantCommentsCopyWithImpl<ConsultantComments>(
this as ConsultantComments, _$identity);
/// Serializes this ConsultantComments to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is ConsultantComments &&
(identical(other.dayComment, dayComment) ||
other.dayComment == dayComment) &&
const DeepCollectionEquality()
.equals(other.mealsComments, mealsComments) &&
const DeepCollectionEquality()
.equals(other.portionsComments, portionsComments));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
dayComment,
const DeepCollectionEquality().hash(mealsComments),
const DeepCollectionEquality().hash(portionsComments));
@override
String toString() {
return 'ConsultantComments(dayComment: $dayComment, mealsComments: $mealsComments, portionsComments: $portionsComments)';
}
}
/// @nodoc
abstract mixin class $ConsultantCommentsCopyWith<$Res> {
factory $ConsultantCommentsCopyWith(
ConsultantComments value, $Res Function(ConsultantComments) _then) =
_$ConsultantCommentsCopyWithImpl;
@useResult
$Res call(
{String? dayComment,
List<MealComment> mealsComments,
List<PortionComment> portionsComments});
}
/// @nodoc
class _$ConsultantCommentsCopyWithImpl<$Res>
implements $ConsultantCommentsCopyWith<$Res> {
_$ConsultantCommentsCopyWithImpl(this._self, this._then);
final ConsultantComments _self;
final $Res Function(ConsultantComments) _then;
/// Create a copy of ConsultantComments
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? dayComment = freezed,
Object? mealsComments = null,
Object? portionsComments = null,
}) {
return _then(_self.copyWith(
dayComment: freezed == dayComment
? _self.dayComment
: dayComment // ignore: cast_nullable_to_non_nullable
as String?,
mealsComments: null == mealsComments
? _self.mealsComments
: mealsComments // ignore: cast_nullable_to_non_nullable
as List<MealComment>,
portionsComments: null == portionsComments
? _self.portionsComments
: portionsComments // ignore: cast_nullable_to_non_nullable
as List<PortionComment>,
));
}
}
/// @nodoc
@JsonSerializable()
class _ConsultantComments implements ConsultantComments {
_ConsultantComments(
{required this.dayComment,
required final List<MealComment> mealsComments,
required final List<PortionComment> portionsComments})
: _mealsComments = mealsComments,
_portionsComments = portionsComments;
factory _ConsultantComments.fromJson(Map<String, dynamic> json) =>
_$ConsultantCommentsFromJson(json);
@override
final String? dayComment;
final List<MealComment> _mealsComments;
@override
List<MealComment> get mealsComments {
if (_mealsComments is EqualUnmodifiableListView) return _mealsComments;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_mealsComments);
}
final List<PortionComment> _portionsComments;
@override
List<PortionComment> get portionsComments {
if (_portionsComments is EqualUnmodifiableListView)
return _portionsComments;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_portionsComments);
}
/// Create a copy of ConsultantComments
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$ConsultantCommentsCopyWith<_ConsultantComments> get copyWith =>
__$ConsultantCommentsCopyWithImpl<_ConsultantComments>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$ConsultantCommentsToJson(
this,
);
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _ConsultantComments &&
(identical(other.dayComment, dayComment) ||
other.dayComment == dayComment) &&
const DeepCollectionEquality()
.equals(other._mealsComments, _mealsComments) &&
const DeepCollectionEquality()
.equals(other._portionsComments, _portionsComments));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
dayComment,
const DeepCollectionEquality().hash(_mealsComments),
const DeepCollectionEquality().hash(_portionsComments));
@override
String toString() {
return 'ConsultantComments(dayComment: $dayComment, mealsComments: $mealsComments, portionsComments: $portionsComments)';
}
}
/// @nodoc
abstract mixin class _$ConsultantCommentsCopyWith<$Res>
implements $ConsultantCommentsCopyWith<$Res> {
factory _$ConsultantCommentsCopyWith(
_ConsultantComments value, $Res Function(_ConsultantComments) _then) =
__$ConsultantCommentsCopyWithImpl;
@override
@useResult
$Res call(
{String? dayComment,
List<MealComment> mealsComments,
List<PortionComment> portionsComments});
}
/// @nodoc
class __$ConsultantCommentsCopyWithImpl<$Res>
implements _$ConsultantCommentsCopyWith<$Res> {
__$ConsultantCommentsCopyWithImpl(this._self, this._then);
final _ConsultantComments _self;
final $Res Function(_ConsultantComments) _then;
/// Create a copy of ConsultantComments
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$Res call({
Object? dayComment = freezed,
Object? mealsComments = null,
Object? portionsComments = null,
}) {
return _then(_ConsultantComments(
dayComment: freezed == dayComment
? _self.dayComment
: dayComment // ignore: cast_nullable_to_non_nullable
as String?,
mealsComments: null == mealsComments
? _self._mealsComments
: mealsComments // ignore: cast_nullable_to_non_nullable
as List<MealComment>,
portionsComments: null == portionsComments
? _self._portionsComments
: portionsComments // ignore: cast_nullable_to_non_nullable
as List<PortionComment>,
));
}
}
/// @nodoc
mixin _$MealComment {
String get comment;
int get typeNo;
/// Create a copy of MealComment
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$MealCommentCopyWith<MealComment> get copyWith =>
_$MealCommentCopyWithImpl<MealComment>(this as MealComment, _$identity);
/// Serializes this MealComment to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is MealComment &&
(identical(other.comment, comment) || other.comment == comment) &&
(identical(other.typeNo, typeNo) || other.typeNo == typeNo));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, comment, typeNo);
@override
String toString() {
return 'MealComment(comment: $comment, typeNo: $typeNo)';
}
}
/// @nodoc
abstract mixin class $MealCommentCopyWith<$Res> {
factory $MealCommentCopyWith(
MealComment value, $Res Function(MealComment) _then) =
_$MealCommentCopyWithImpl;
@useResult
$Res call({String comment, int typeNo});
}
/// @nodoc
class _$MealCommentCopyWithImpl<$Res> implements $MealCommentCopyWith<$Res> {
_$MealCommentCopyWithImpl(this._self, this._then);
final MealComment _self;
final $Res Function(MealComment) _then;
/// Create a copy of MealComment
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? comment = null,
Object? typeNo = null,
}) {
return _then(_self.copyWith(
comment: null == comment
? _self.comment
: comment // ignore: cast_nullable_to_non_nullable
as String,
typeNo: null == typeNo
? _self.typeNo
: typeNo // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
/// @nodoc
@JsonSerializable()
class _MealComment implements MealComment {
_MealComment({required this.comment, required this.typeNo});
factory _MealComment.fromJson(Map<String, dynamic> json) =>
_$MealCommentFromJson(json);
@override
final String comment;
@override
final int typeNo;
/// Create a copy of MealComment
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$MealCommentCopyWith<_MealComment> get copyWith =>
__$MealCommentCopyWithImpl<_MealComment>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$MealCommentToJson(
this,
);
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _MealComment &&
(identical(other.comment, comment) || other.comment == comment) &&
(identical(other.typeNo, typeNo) || other.typeNo == typeNo));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, comment, typeNo);
@override
String toString() {
return 'MealComment(comment: $comment, typeNo: $typeNo)';
}
}
/// @nodoc
abstract mixin class _$MealCommentCopyWith<$Res>
implements $MealCommentCopyWith<$Res> {
factory _$MealCommentCopyWith(
_MealComment value, $Res Function(_MealComment) _then) =
__$MealCommentCopyWithImpl;
@override
@useResult
$Res call({String comment, int typeNo});
}
/// @nodoc
class __$MealCommentCopyWithImpl<$Res> implements _$MealCommentCopyWith<$Res> {
__$MealCommentCopyWithImpl(this._self, this._then);
final _MealComment _self;
final $Res Function(_MealComment) _then;
/// Create a copy of MealComment
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$Res call({
Object? comment = null,
Object? typeNo = null,
}) {
return _then(_MealComment(
comment: null == comment
? _self.comment
: comment // ignore: cast_nullable_to_non_nullable
as String,
typeNo: null == typeNo
? _self.typeNo
: typeNo // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
/// @nodoc
mixin _$PortionComment {
@JsonKey(name: 'id')
int get portionId;
String get comment;
/// Create a copy of PortionComment
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$PortionCommentCopyWith<PortionComment> get copyWith =>
_$PortionCommentCopyWithImpl<PortionComment>(
this as PortionComment, _$identity);
/// Serializes this PortionComment to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is PortionComment &&
(identical(other.portionId, portionId) ||
other.portionId == portionId) &&
(identical(other.comment, comment) || other.comment == comment));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, portionId, comment);
@override
String toString() {
return 'PortionComment(portionId: $portionId, comment: $comment)';
}
}
/// @nodoc
abstract mixin class $PortionCommentCopyWith<$Res> {
factory $PortionCommentCopyWith(
PortionComment value, $Res Function(PortionComment) _then) =
_$PortionCommentCopyWithImpl;
@useResult
$Res call({@JsonKey(name: 'id') int portionId, String comment});
}
/// @nodoc
class _$PortionCommentCopyWithImpl<$Res>
implements $PortionCommentCopyWith<$Res> {
_$PortionCommentCopyWithImpl(this._self, this._then);
final PortionComment _self;
final $Res Function(PortionComment) _then;
/// Create a copy of PortionComment
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? portionId = null,
Object? comment = null,
}) {
return _then(_self.copyWith(
portionId: null == portionId
? _self.portionId
: portionId // ignore: cast_nullable_to_non_nullable
as int,
comment: null == comment
? _self.comment
: comment // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
@JsonSerializable()
class _PortionComment implements PortionComment {
_PortionComment(
{@JsonKey(name: 'id') required this.portionId, required this.comment});
factory _PortionComment.fromJson(Map<String, dynamic> json) =>
_$PortionCommentFromJson(json);
@override
@JsonKey(name: 'id')
final int portionId;
@override
final String comment;
/// Create a copy of PortionComment
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$PortionCommentCopyWith<_PortionComment> get copyWith =>
__$PortionCommentCopyWithImpl<_PortionComment>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$PortionCommentToJson(
this,
);
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _PortionComment &&
(identical(other.portionId, portionId) ||
other.portionId == portionId) &&
(identical(other.comment, comment) || other.comment == comment));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, portionId, comment);
@override
String toString() {
return 'PortionComment(portionId: $portionId, comment: $comment)';
}
}
/// @nodoc
abstract mixin class _$PortionCommentCopyWith<$Res>
implements $PortionCommentCopyWith<$Res> {
factory _$PortionCommentCopyWith(
_PortionComment value, $Res Function(_PortionComment) _then) =
__$PortionCommentCopyWithImpl;
@override
@useResult
$Res call({@JsonKey(name: 'id') int portionId, String comment});
}
/// @nodoc
class __$PortionCommentCopyWithImpl<$Res>
implements _$PortionCommentCopyWith<$Res> {
__$PortionCommentCopyWithImpl(this._self, this._then);
final _PortionComment _self;
final $Res Function(_PortionComment) _then;
/// Create a copy of PortionComment
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$Res call({
Object? portionId = null,
Object? comment = null,
}) {
return _then(_PortionComment(
portionId: null == portionId
? _self.portionId
: portionId // ignore: cast_nullable_to_non_nullable
as int,
comment: null == comment
? _self.comment
: comment // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
// dart format on

View File

@@ -1,67 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'consultant_review_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_ConsultantReviewModel _$ConsultantReviewModelFromJson(
Map<String, dynamic> json) =>
_ConsultantReviewModel(
planName: json['planName'] as String,
planDuration: (json['planDuration'] as num).toInt(),
currentPlanDay: (json['currentPlanDay'] as num).toInt(),
consultantComments: ConsultantComments.fromJson(
json['consultantComments'] as Map<String, dynamic>),
);
Map<String, dynamic> _$ConsultantReviewModelToJson(
_ConsultantReviewModel instance) =>
<String, dynamic>{
'planName': instance.planName,
'planDuration': instance.planDuration,
'currentPlanDay': instance.currentPlanDay,
'consultantComments': instance.consultantComments,
};
_ConsultantComments _$ConsultantCommentsFromJson(Map<String, dynamic> json) =>
_ConsultantComments(
dayComment: json['dayComment'] as String?,
mealsComments: (json['mealsComments'] as List<dynamic>)
.map((e) => MealComment.fromJson(e as Map<String, dynamic>))
.toList(),
portionsComments: (json['portionsComments'] as List<dynamic>)
.map((e) => PortionComment.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$ConsultantCommentsToJson(_ConsultantComments instance) =>
<String, dynamic>{
'dayComment': instance.dayComment,
'mealsComments': instance.mealsComments,
'portionsComments': instance.portionsComments,
};
_MealComment _$MealCommentFromJson(Map<String, dynamic> json) => _MealComment(
comment: json['comment'] as String,
typeNo: (json['typeNo'] as num).toInt(),
);
Map<String, dynamic> _$MealCommentToJson(_MealComment instance) =>
<String, dynamic>{
'comment': instance.comment,
'typeNo': instance.typeNo,
};
_PortionComment _$PortionCommentFromJson(Map<String, dynamic> json) =>
_PortionComment(
portionId: (json['id'] as num).toInt(),
comment: json['comment'] as String,
);
Map<String, dynamic> _$PortionCommentToJson(_PortionComment instance) =>
<String, dynamic>{
'id': instance.portionId,
'comment': instance.comment,
};

View File

@@ -208,7 +208,7 @@ class _AboutPlanScreenState extends State<AboutPlanScreen> {
GoRouter.of(context).pushReplacementNamed(
'chatScreen',
extra: {
'chatId': chosenPlan.chatId,
'uuid': chosenPlan.chatId,
'sendInitialMessage': true,
},
);

View File

@@ -17,6 +17,7 @@ abstract class ProfileModel with _$ProfileModel {
@JsonKey(name: "created_at") DateTime? createdAt,
@JsonKey(name: "updated_at") DateTime? updatedAt,
@JsonKey(name: "is_public_profile", fromJson: parseBool) required bool isPublicProfile,
@JsonKey(name: "is_blocked_by_me", fromJson: parseBool) required bool isBlockedByMe,
@JsonKey(name: 'is_entity_subscribed_by_me') required bool isEntitySubscribedByMe,
@JsonKey(name: "slug") required String slug,
@JsonKey(name: "profile_photo_url") required String profilePhotoUrl,

View File

@@ -25,6 +25,7 @@ class ProfileCubit extends Cubit<ProfileState> {
}) : super(const ProfileState.loading());
Future<void> getProfileBySlug(String slug) async {
emit(const ProfileState.loading());
try {
final profile = await profileRepository.getProfileBySlug(slug);
emit(
@@ -44,6 +45,7 @@ class ProfileCubit extends Cubit<ProfileState> {
Future<void> getMyProfile({
String period = '1',
}) async {
emit(const ProfileState.loading());
_currentPeriod = period;
try {
final profile = await profileRepository.getMyProfile();
@@ -123,7 +125,7 @@ class ProfileCubit extends Cubit<ProfileState> {
AppRouter.navigatorKey.currentContext?.pushNamed(
'chatScreen',
extra: {
'chatId': chatIdOrError,
'uuid': chatIdOrError,
},
);
return chatIdOrError;

View File

@@ -194,9 +194,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
],
),
if (state.profileDetails.additionalInfo.isNotEmpty) _additionalInfo(state),
const SizedBox(height: 8),
_messageAndSubscribe(state),
const SizedBox(height: 16),
if (!state.profile.isBlockedByMe) const SizedBox(height: 8),
if (!state.profile.isBlockedByMe) _messageAndSubscribe(state),
if (!state.profile.isBlockedByMe) const SizedBox(height: 16),
],
),
),
@@ -1177,7 +1177,21 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
);
} else if (value == 'block') {
isFirstFetch = true;
sl<BlockedUsersCubit>().blockUser(state.profile.slug);
widget.author == null || widget.author!.authorIsMe ? profileCubit.getMyProfile() : profileCubit.getProfileBySlug(widget.author!.authorSlug);
if (state.profile.roles.contains('consultant')) {
plansCubit.getPlans(state.profile.slug);
}
isFirstFetch = false;
} else if (value == 'unblock') {
isFirstFetch = true;
sl<BlockedUsersCubit>().unblockUser(state.profile.slug);
widget.author == null || widget.author!.authorIsMe ? profileCubit.getMyProfile() : profileCubit.getProfileBySlug(widget.author!.authorSlug);
if (state.profile.roles.contains('consultant')) {
plansCubit.getPlans(state.profile.slug);
}
isFirstFetch = false;
} else {
showModalBottomSheet(
context: context,
@@ -1199,11 +1213,16 @@ class _ProfileScreenState extends State<ProfileScreen> {
value: 'complain',
child: Text('Пожаловаться'),
),
if (widget.author != null)
if (widget.author != null && !state.profile.isBlockedByMe)
const PopupMenuItem(
value: 'block',
child: Text('Заблокировать'),
),
if (widget.author != null && state.profile.isBlockedByMe)
const PopupMenuItem(
value: 'unblock',
child: Text('Разблокировать'),
),
],
child: const Icon(Icons.more_horiz_rounded),
),

View File

@@ -69,7 +69,7 @@ class _SubActionButtonWidgetState extends State<SubActionButtonWidget> {
GoRouter.of(context).pushNamed(
'chatScreen',
extra: {
'chatId': await sl<ProfileCubit>().getChatRoomIdBySlug(
'uuid': await sl<ProfileCubit>().getChatRoomIdBySlug(
author: Author(
authorSlug: widget.slug,
authorName: widget.name,

View File

@@ -3,7 +3,6 @@ import 'dart:developer';
import 'package:eatvio_app/core/app_router.dart';
import 'package:eatvio_app/core/token_storage.dart';
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
import 'package:eatvio_app/features/registration/models/user_registration_model.dart';
import 'package:eatvio_app/features/registration/presentation/bloc/registration_cubit/registration_state.dart';
import 'package:eatvio_app/features/registration/repositories/registration_repository.dart';
@@ -51,25 +50,17 @@ class RegistrationCubit extends Cubit<RegistrationState> {
void updateSheet(UserRegistrationSheet sheet) => emit(RegistrationState(sheet: sheet));
Future<void> tryRegistration() async {
if (await registrationRepository.emailIsReachable(state.sheet.email)) {
try {
final token = await registrationRepository.tryRegister(
state.sheet.copyWith(
phone: state.sheet.phone.replaceAll(' ', '').replaceAll('(', '').replaceAll(')', ''),
responseBody: '{}',
),
);
await TokenStorage.saveTokenInStorage(token);
AppRouter.navigatorKey.currentContext?.pushNamed('verifyEmailScreen');
} catch (e) {
log(e.toString());
}
} else {
showErrorDialog(
AppRouter.navigatorKey.currentContext!,
title: 'Ошибка регистрации',
description: 'Несуществующая почта.',
try {
final token = await registrationRepository.tryRegister(
state.sheet.copyWith(
phone: state.sheet.phone.replaceAll(' ', '').replaceAll('(', '').replaceAll(')', ''),
responseBody: '{}',
),
);
await TokenStorage.saveTokenInStorage(token);
AppRouter.navigatorKey.currentContext?.pushNamed('verifyEmailScreen');
} catch (e, st) {
log(e.toString(), stackTrace: st);
}
}

View File

@@ -1,5 +1,7 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/utils/toasts.dart';
import 'package:eatvio_app/features/registration/models/user_registration_model.dart';
import 'package:eatvio_app/features/registration/models/location_model.dart';
import 'package:eatvio_app/features/registration/services/registration_service.dart';
@@ -11,7 +13,13 @@ class RegistrationRepository {
Future<String> tryRegister(UserRegistrationSheet sheet) async {
try {
return (await registrationService.register(sheet: sheet.toJson()))['token']!;
final response = await registrationService.register(sheet: sheet.toJson());
try {
return (response['token']!);
} catch (e) {
showErrorToast(response.toString());
rethrow;
}
} catch (e) {
rethrow;
}

View File

@@ -1,6 +1,6 @@
name: eatvio_app
description: A new Flutter project.
version: 1.1.16+46
version: 1.2.2+52
publish_to: 'none'
environment:

View File

@@ -21,6 +21,7 @@ void main() {
email: 'mso7nueh@mail.ru',
isPublicProfile: true,
isEntitySubscribedByMe: false,
isBlockedByMe: false,
slug: 'slug',
profilePhotoUrl: '',
roles: ['user'],

View File

@@ -1,526 +0,0 @@
// Mocks generated by Mockito 5.4.6 from annotations
// in eatvio_app/test/features/profile/services/profile_service_test.dart.
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i6;
import 'dart:io' as _i10;
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart'
as _i7;
import 'package:eatvio_app/features/profile/models/chosen_diets_pagination_model.dart'
as _i4;
import 'package:eatvio_app/features/profile/models/circumference_model.dart'
as _i9;
import 'package:eatvio_app/features/profile/models/profile_model.dart' as _i2;
import 'package:eatvio_app/features/profile/models/sub_model.dart' as _i3;
import 'package:eatvio_app/features/profile/models/weight_model.dart' as _i8;
import 'package:eatvio_app/features/profile/services/profile_service.dart'
as _i5;
import 'package:mockito/mockito.dart' as _i1;
import 'package:mockito/src/dummies.dart' as _i11;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
// ignore_for_file: avoid_setters_without_getters
// ignore_for_file: comment_references
// ignore_for_file: deprecated_member_use
// ignore_for_file: deprecated_member_use_from_same_package
// ignore_for_file: implementation_imports
// ignore_for_file: invalid_use_of_visible_for_testing_member
// ignore_for_file: must_be_immutable
// ignore_for_file: prefer_const_constructors
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: camel_case_types
// ignore_for_file: subtype_of_sealed_class
class _FakeProfileModel_0 extends _i1.SmartFake implements _i2.ProfileModel {
_FakeProfileModel_0(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeProfileDetailsModel_1 extends _i1.SmartFake
implements _i2.ProfileDetailsModel {
_FakeProfileDetailsModel_1(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeSubPaginationModel_2 extends _i1.SmartFake
implements _i3.SubPaginationModel {
_FakeSubPaginationModel_2(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
class _FakeChosenDietsPaginationModel_3 extends _i1.SmartFake
implements _i4.ChosenDietsPaginationModel {
_FakeChosenDietsPaginationModel_3(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
/// A class which mocks [ProfileService].
///
/// See the documentation for Mockito's code generation for more information.
class MockProfileService extends _i1.Mock implements _i5.ProfileService {
@override
_i6.Future<_i2.ProfileModel> getProfileBySlug({required String? slug}) =>
(super.noSuchMethod(
Invocation.method(
#getProfileBySlug,
[],
{#slug: slug},
),
returnValue: _i6.Future<_i2.ProfileModel>.value(_FakeProfileModel_0(
this,
Invocation.method(
#getProfileBySlug,
[],
{#slug: slug},
),
)),
returnValueForMissingStub:
_i6.Future<_i2.ProfileModel>.value(_FakeProfileModel_0(
this,
Invocation.method(
#getProfileBySlug,
[],
{#slug: slug},
),
)),
) as _i6.Future<_i2.ProfileModel>);
@override
_i6.Future<_i2.ProfileModel> getMyProfile() => (super.noSuchMethod(
Invocation.method(
#getMyProfile,
[],
),
returnValue: _i6.Future<_i2.ProfileModel>.value(_FakeProfileModel_0(
this,
Invocation.method(
#getMyProfile,
[],
),
)),
returnValueForMissingStub:
_i6.Future<_i2.ProfileModel>.value(_FakeProfileModel_0(
this,
Invocation.method(
#getMyProfile,
[],
),
)),
) as _i6.Future<_i2.ProfileModel>);
@override
_i6.Future<_i2.ProfileDetailsModel> getMyProfileDetails() =>
(super.noSuchMethod(
Invocation.method(
#getMyProfileDetails,
[],
),
returnValue: _i6.Future<_i2.ProfileDetailsModel>.value(
_FakeProfileDetailsModel_1(
this,
Invocation.method(
#getMyProfileDetails,
[],
),
)),
returnValueForMissingStub: _i6.Future<_i2.ProfileDetailsModel>.value(
_FakeProfileDetailsModel_1(
this,
Invocation.method(
#getMyProfileDetails,
[],
),
)),
) as _i6.Future<_i2.ProfileDetailsModel>);
@override
_i6.Future<_i2.ProfileDetailsModel> getProfileDetailsBySlug(
{required String? slug}) =>
(super.noSuchMethod(
Invocation.method(
#getProfileDetailsBySlug,
[],
{#slug: slug},
),
returnValue: _i6.Future<_i2.ProfileDetailsModel>.value(
_FakeProfileDetailsModel_1(
this,
Invocation.method(
#getProfileDetailsBySlug,
[],
{#slug: slug},
),
)),
returnValueForMissingStub: _i6.Future<_i2.ProfileDetailsModel>.value(
_FakeProfileDetailsModel_1(
this,
Invocation.method(
#getProfileDetailsBySlug,
[],
{#slug: slug},
),
)),
) as _i6.Future<_i2.ProfileDetailsModel>);
@override
_i6.Future<void> addCircumference({
required int? chestCircumference,
required int? waistCircumference,
required int? hipCircumference,
}) =>
(super.noSuchMethod(
Invocation.method(
#addCircumference,
[],
{
#chestCircumference: chestCircumference,
#waistCircumference: waistCircumference,
#hipCircumference: hipCircumference,
},
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<void> addWeight({required double? weight}) => (super.noSuchMethod(
Invocation.method(
#addWeight,
[],
{#weight: weight},
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<List<_i7.FeedBlogPostModel>> getBlogPostByAuthorSlug(
{required String? slug}) =>
(super.noSuchMethod(
Invocation.method(
#getBlogPostByAuthorSlug,
[],
{#slug: slug},
),
returnValue: _i6.Future<List<_i7.FeedBlogPostModel>>.value(
<_i7.FeedBlogPostModel>[]),
returnValueForMissingStub:
_i6.Future<List<_i7.FeedBlogPostModel>>.value(
<_i7.FeedBlogPostModel>[]),
) as _i6.Future<List<_i7.FeedBlogPostModel>>);
@override
_i6.Future<List<_i8.WeightModel>> getWeight({required String? period}) =>
(super.noSuchMethod(
Invocation.method(
#getWeight,
[],
{#period: period},
),
returnValue:
_i6.Future<List<_i8.WeightModel>>.value(<_i8.WeightModel>[]),
returnValueForMissingStub:
_i6.Future<List<_i8.WeightModel>>.value(<_i8.WeightModel>[]),
) as _i6.Future<List<_i8.WeightModel>>);
@override
_i6.Future<List<_i8.WeightModel>> getWeightBySlug({
required String? period,
required String? slug,
}) =>
(super.noSuchMethod(
Invocation.method(
#getWeightBySlug,
[],
{
#period: period,
#slug: slug,
},
),
returnValue:
_i6.Future<List<_i8.WeightModel>>.value(<_i8.WeightModel>[]),
returnValueForMissingStub:
_i6.Future<List<_i8.WeightModel>>.value(<_i8.WeightModel>[]),
) as _i6.Future<List<_i8.WeightModel>>);
@override
_i6.Future<List<_i9.CircumferenceModel>> getCircumferences(
{required String? period}) =>
(super.noSuchMethod(
Invocation.method(
#getCircumferences,
[],
{#period: period},
),
returnValue: _i6.Future<List<_i9.CircumferenceModel>>.value(
<_i9.CircumferenceModel>[]),
returnValueForMissingStub:
_i6.Future<List<_i9.CircumferenceModel>>.value(
<_i9.CircumferenceModel>[]),
) as _i6.Future<List<_i9.CircumferenceModel>>);
@override
_i6.Future<List<_i9.CircumferenceModel>> getCircumferencesBySlug({
required String? period,
required String? slug,
}) =>
(super.noSuchMethod(
Invocation.method(
#getCircumferencesBySlug,
[],
{
#period: period,
#slug: slug,
},
),
returnValue: _i6.Future<List<_i9.CircumferenceModel>>.value(
<_i9.CircumferenceModel>[]),
returnValueForMissingStub:
_i6.Future<List<_i9.CircumferenceModel>>.value(
<_i9.CircumferenceModel>[]),
) as _i6.Future<List<_i9.CircumferenceModel>>);
@override
_i6.Future<_i3.SubPaginationModel> getSubscribers({
required String? slug,
String? query,
}) =>
(super.noSuchMethod(
Invocation.method(
#getSubscribers,
[],
{
#slug: slug,
#query: query,
},
),
returnValue:
_i6.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2(
this,
Invocation.method(
#getSubscribers,
[],
{
#slug: slug,
#query: query,
},
),
)),
returnValueForMissingStub:
_i6.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2(
this,
Invocation.method(
#getSubscribers,
[],
{
#slug: slug,
#query: query,
},
),
)),
) as _i6.Future<_i3.SubPaginationModel>);
@override
_i6.Future<_i3.SubPaginationModel> getSubscriptions({
required String? slug,
String? query,
}) =>
(super.noSuchMethod(
Invocation.method(
#getSubscriptions,
[],
{
#slug: slug,
#query: query,
},
),
returnValue:
_i6.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2(
this,
Invocation.method(
#getSubscriptions,
[],
{
#slug: slug,
#query: query,
},
),
)),
returnValueForMissingStub:
_i6.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2(
this,
Invocation.method(
#getSubscriptions,
[],
{
#slug: slug,
#query: query,
},
),
)),
) as _i6.Future<_i3.SubPaginationModel>);
@override
_i6.Future<void> subscribe({required String? slug}) => (super.noSuchMethod(
Invocation.method(
#subscribe,
[],
{#slug: slug},
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<void> unsubscribe({required String? slug}) => (super.noSuchMethod(
Invocation.method(
#unsubscribe,
[],
{#slug: slug},
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<void> uploadPhoto({required _i10.File? photo}) =>
(super.noSuchMethod(
Invocation.method(
#uploadPhoto,
[],
{#photo: photo},
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<void> deletePhoto() => (super.noSuchMethod(
Invocation.method(
#deletePhoto,
[],
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<_i4.ChosenDietsPaginationModel> getChosenDiets() =>
(super.noSuchMethod(
Invocation.method(
#getChosenDiets,
[],
),
returnValue: _i6.Future<_i4.ChosenDietsPaginationModel>.value(
_FakeChosenDietsPaginationModel_3(
this,
Invocation.method(
#getChosenDiets,
[],
),
)),
returnValueForMissingStub:
_i6.Future<_i4.ChosenDietsPaginationModel>.value(
_FakeChosenDietsPaginationModel_3(
this,
Invocation.method(
#getChosenDiets,
[],
),
)),
) as _i6.Future<_i4.ChosenDietsPaginationModel>);
@override
_i6.Future<String> getPassKey({required String? json}) => (super.noSuchMethod(
Invocation.method(
#getPassKey,
[],
{#json: json},
),
returnValue: _i6.Future<String>.value(_i11.dummyValue<String>(
this,
Invocation.method(
#getPassKey,
[],
{#json: json},
),
)),
returnValueForMissingStub:
_i6.Future<String>.value(_i11.dummyValue<String>(
this,
Invocation.method(
#getPassKey,
[],
{#json: json},
),
)),
) as _i6.Future<String>);
@override
_i6.Future<String> getMyPhone() => (super.noSuchMethod(
Invocation.method(
#getMyPhone,
[],
),
returnValue: _i6.Future<String>.value(_i11.dummyValue<String>(
this,
Invocation.method(
#getMyPhone,
[],
),
)),
returnValueForMissingStub:
_i6.Future<String>.value(_i11.dummyValue<String>(
this,
Invocation.method(
#getMyPhone,
[],
),
)),
) as _i6.Future<String>);
@override
_i6.Future<void> sendEmailCode() => (super.noSuchMethod(
Invocation.method(
#sendEmailCode,
[],
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
@override
_i6.Future<void> tryVerifyEmailByCode({required String? code}) =>
(super.noSuchMethod(
Invocation.method(
#tryVerifyEmailByCode,
[],
{#code: code},
),
returnValue: _i6.Future<void>.value(),
returnValueForMissingStub: _i6.Future<void>.value(),
) as _i6.Future<void>);
}