diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 2ee97ce4..63d0dd02 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -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 = 24; + CURRENT_PROJECT_VERSION = 25; 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 = 24; + CURRENT_PROJECT_VERSION = 25; 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 = 24; + CURRENT_PROJECT_VERSION = 25; DEVELOPMENT_TEAM = VL68C36HYS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index a88158e2..2f074053 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -21,7 +21,7 @@ CFBundleSignature ???? CFBundleVersion - 24 + 25 ITSAppUsesNonExemptEncryption LSRequiresIPhoneOS diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart index 32358505..c849628d 100644 --- a/lib/core/app_router.dart +++ b/lib/core/app_router.dart @@ -364,9 +364,12 @@ class AppRouter { path: UserDiaryScreen.path, name: UserDiaryScreen.name, builder: (context, state) { - final diaryId = state.extra as int; + final data = state.extra as Map; + final diaryId = data['diaryId'] as int; + final currentPlanDay = data['currentDiaryDay'] as int; return UserDiaryScreen( diaryId: diaryId, + currentPlanDay: currentPlanDay, ); }, ), diff --git a/lib/features/blog_post/presentation/pages/blog_post_screen.dart b/lib/features/blog_post/presentation/pages/blog_post_screen.dart index ad85dcc7..f597c244 100644 --- a/lib/features/blog_post/presentation/pages/blog_post_screen.dart +++ b/lib/features/blog_post/presentation/pages/blog_post_screen.dart @@ -215,7 +215,10 @@ class _BlogPostScreenState extends State { child: Html(data: widget.blogPost.description, style: {"*": Style(color: Colors.black87)}), ), const SizedBox(height: 8), - CachedNetworkImage(imageUrl: '$baseUrl/storage/${widget.blogPost.image}'), + if (widget.blogPost.image.isNotEmpty) + CachedNetworkImage( + imageUrl: '$baseUrl/storage/${widget.blogPost.image}', + ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( diff --git a/lib/features/blog_post_create/repositories/blog_post_repository.dart b/lib/features/blog_post_create/repositories/blog_post_repository.dart index af796f14..aeea8474 100644 --- a/lib/features/blog_post_create/repositories/blog_post_repository.dart +++ b/lib/features/blog_post_create/repositories/blog_post_repository.dart @@ -73,7 +73,7 @@ class BlogPostRepository { 'video_url': videoUrl, 'image': image != null ? await MultipartFile.fromFile((await ImageCompressUtility.compressFile(File(image.path))).path, filename: image.name) - : oldImageUrl != null + : oldImageUrl != '' && oldImageUrl != null ? await MultipartFile.fromFile((await downloadImage(oldImageUrl))?.path ?? '', filename: oldImageUrl.split('/').last) : null, }); 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 d35fec90..58a53ac0 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 @@ -28,8 +28,22 @@ class ChatRoomCubit extends Cubit { int currentPage = 1; late int lastPage; bool isLoading = false; + Timer? _timer; - ChatRoomCubit({required this.chatRepository, required this.wsManager, required this.cardsRepository}) : super(const ChatRoomState.loading()); + ChatRoomCubit({ + required this.chatRepository, + required this.wsManager, + required this.cardsRepository, + }) : super(const ChatRoomState.loading()); + + void setTimer() { + _timer?.cancel(); + _timer = Timer.periodic(const Duration(seconds: 5), (_) => updateChosenPlanState()); + } + + void cancelTimer() { + _timer?.cancel(); + } loadNextPage(String chatId) async { if (currentPage < lastPage && !isLoading) { @@ -97,7 +111,6 @@ class ChatRoomCubit extends Cubit { if (chosenPlan?.consultantId == chatRoom.users.sender.id) { await checkCards(); } - } catch (e) { log(e.toString()); typingSubscription?.cancel(); @@ -234,6 +247,7 @@ class ChatRoomCubit extends Cubit { @override Future close() async { wsManager.unsubscribeDirectChatChannel(); + _timer?.cancel(); messagesSubscription?.cancel(); typingSubscription?.cancel(); super.close(); diff --git a/lib/features/chat/presentation/pages/chat_screen.dart b/lib/features/chat/presentation/pages/chat_screen.dart index 72c97a6d..9cd3ff71 100644 --- a/lib/features/chat/presentation/pages/chat_screen.dart +++ b/lib/features/chat/presentation/pages/chat_screen.dart @@ -44,12 +44,24 @@ class _ChatScreenState extends State { final List<({int id, int index})> unreadMessagesIds = []; final List<({int id, int index})> unreadMessagesIdsCopy = []; final showableChatBadgeStates = ChosenPlanStateEnum.getShowableChatBadgeStates(); + late AppLifecycleListener _listener; + + void _onHide() { + chatRoomCubit.cancelTimer(); + } + + void _onResume() { + chatRoomCubit.updateChosenPlanState(); + chatRoomCubit.setTimer(); + } @override void initState() { super.initState(); scrollController.addListener(_onScroll); chatRoomCubit.initChat(widget.chatId, sendInitialMessage: widget.sendInitialMessage ?? false); + chatRoomCubit.setTimer(); + _listener = AppLifecycleListener(onHide: _onHide, onResume: _onResume); } _onScroll() { @@ -61,6 +73,7 @@ class _ChatScreenState extends State { @override void dispose() { scrollController.dispose(); + _listener.dispose(); chatRoomCubit.close(); super.dispose(); } @@ -96,7 +109,7 @@ class _ChatScreenState extends State { final showAboutOrderButton = state.chatRoom.chosenPlan != null && state.chatRoom.chosenPlan!.chosenPlanState != ChosenPlanStateEnum.stateCanceledByTheInitiator; BannerType? bannerType; - if (chosenPlan == null) { + if (chosenPlan == null || chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateCanceledByTheInitiator) { bannerType = null; } else if (amIConsultant && !state.hasCard) { bannerType = BannerType.card; diff --git a/lib/features/consultations/presentation/widgets/consultation_card_widget.dart b/lib/features/consultations/presentation/widgets/consultation_card_widget.dart index 0752847b..c9b9f8b2 100644 --- a/lib/features/consultations/presentation/widgets/consultation_card_widget.dart +++ b/lib/features/consultations/presentation/widgets/consultation_card_widget.dart @@ -197,7 +197,10 @@ class _ConsultationCardWidgetState extends State { title: s.you_can_not_open_this_day, description: '${widget.consultationsModel.userName} ${s.has_not_filled_it_yet}'); return; } - GoRouter.of(context).push(UserDiaryScreen.path, extra: day.$2.id); + GoRouter.of(context).push(UserDiaryScreen.path, extra: { + 'diaryId': day.$2.id, + 'currentDiaryDay': index + 1, + }); }, borderRadius: BorderRadius.circular(100), child: Ink( @@ -293,6 +296,10 @@ class _ConsultationCardWidgetState extends State { ) .lastOrNull; if (lastActiveDay != null) { + GoRouter.of(context).push(UserDiaryScreen.path, extra: { + 'diaryId': lastActiveDay.$2.id, + 'currentDiaryDay': lastActiveDay.$1, + }); GoRouter.of(context).push(UserDiaryScreen.path, extra: lastActiveDay.$2.id); return; } diff --git a/lib/features/diary/presentation/bloc/diary_cubit.dart b/lib/features/diary/presentation/bloc/diary_cubit.dart index 425c95a7..afe81398 100644 --- a/lib/features/diary/presentation/bloc/diary_cubit.dart +++ b/lib/features/diary/presentation/bloc/diary_cubit.dart @@ -151,7 +151,7 @@ class DiaryCubit extends Cubit { return false; } - fetchDiary([bool needLoading = false, int? diaryId]) async { + fetchDiary([bool needLoading = false, int? diaryId, int? currentDay]) async { this.diaryId ??= diaryId; if (needLoading) { @@ -175,7 +175,7 @@ class DiaryCubit extends Cubit { final chosenPlanModel = await chatRepository.getChosenPlan(id: diaryDay.chosenPlanId!); planDuration = chosenPlanModel.plan.duration; planName = chosenPlanModel.plan.name; - currentPlanDay = DateTime.now().difference(chosenPlanModel.startDate).inDays + 1; + currentPlanDay = currentDay ?? DateTime.now().difference(chosenPlanModel.startDate).inDays + 1; } final nutrition = await getNutrition(diaryDay.id); diff --git a/lib/features/diary/presentation/pages/diary_screen.dart b/lib/features/diary/presentation/pages/diary_screen.dart index 047d660f..2f80c22e 100644 --- a/lib/features/diary/presentation/pages/diary_screen.dart +++ b/lib/features/diary/presentation/pages/diary_screen.dart @@ -2,6 +2,7 @@ import 'dart:developer'; import 'package:eatvio_app/core/theme/custom_text_style.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; +import 'package:eatvio_app/core/utils/date_time_utils.dart'; import 'package:eatvio_app/core/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/core/widgets/data_error_widget.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; @@ -34,24 +35,33 @@ class DiaryScreen extends StatelessWidget { class UserDiaryScreen extends StatelessWidget { static const path = '/user-diary-screen'; static const name = 'userDiaryScreen'; - const UserDiaryScreen({super.key, required this.diaryId}); + const UserDiaryScreen({ + super.key, + required this.diaryId, + required this.currentPlanDay, + }); final int diaryId; + final int currentPlanDay; @override Widget build(BuildContext context) { - return DiaryScreenContent(diaryId: diaryId); + return DiaryScreenContent( + diaryId: diaryId, + currentPlanDay: currentPlanDay, + ); } } class DiaryScreenContent extends StatelessWidget { - const DiaryScreenContent({super.key, this.diaryId}); + const DiaryScreenContent({super.key, this.diaryId, this.currentPlanDay}); final int? diaryId; + final int? currentPlanDay; @override Widget build(BuildContext context) { final s = S.of(context); return MultiBlocProvider( providers: [ BlocProvider( - create: (BuildContext context) => sl()..fetchDiary(true, diaryId), + create: (BuildContext context) => sl()..fetchDiary(true, diaryId, currentPlanDay), ), BlocProvider( create: (context) => sl(), @@ -71,10 +81,14 @@ class DiaryScreenContent extends StatelessWidget { return Scaffold( backgroundColor: Colors.grey.shade200, appBar: AppBar( - toolbarHeight: 0, + title: Text( + state is DiaryStateLoaded ? DateTime.parse(state.diary.date).toLocal().format('d MMMM') : '', + style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black), + ), + centerTitle: true, ), body: SingleChildScrollView( - padding: const EdgeInsets.only(bottom: 16), + padding: const EdgeInsets.only(bottom: 16, top: 8), physics: const BouncingScrollPhysics(), child: Column( children: [ diff --git a/lib/features/feed/models/diets_pagination_model.dart b/lib/features/feed/models/diets_pagination_model.dart index d519d963..5da0bf7e 100644 --- a/lib/features/feed/models/diets_pagination_model.dart +++ b/lib/features/feed/models/diets_pagination_model.dart @@ -20,7 +20,7 @@ abstract class DietsPagination with _$DietsPagination { abstract class Diet with _$Diet { const factory Diet({ @JsonKey(name: "id") required int id, - @JsonKey(name: "slug") String? slug, + @JsonKey(name: "slug") required String slug, @JsonKey(name: "name") required String name, @JsonKey(name: "image") required String image, @JsonKey(name: "duration") required int duration, diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 0bfd0ea0..34d632d2 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -28,10 +28,9 @@ class S { static const AppLocalizationDelegate delegate = AppLocalizationDelegate(); static Future load(Locale locale) { - final name = - (locale.countryCode?.isEmpty ?? false) - ? locale.languageCode - : locale.toString(); + final name = (locale.countryCode?.isEmpty ?? false) + ? locale.languageCode + : locale.toString(); final localeName = Intl.canonicalizedLocale(name); return initializeMessages(localeName).then((_) { Intl.defaultLocale = localeName; diff --git a/pubspec.yaml b/pubspec.yaml index 97712189..34560571 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: eatvio_app description: A new Flutter project. -version: 1.1.2+32 +version: 1.1.3+33 publish_to: 'none' environment: