diff --git a/android/build.gradle b/android/build.gradle
index d2ffbffa..9db63328 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -2,6 +2,7 @@ allprojects {
repositories {
google()
mavenCentral()
+ maven { url 'https://developer.huawei.com/repo/' }
}
}
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 1fee690d..8e9edd22 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 = 73;
+ CURRENT_PROJECT_VERSION = 74;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -539,7 +539,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 73;
+ CURRENT_PROJECT_VERSION = 74;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -578,7 +578,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution: ITVIO, OOO (VL68C36HYS)";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 73;
+ CURRENT_PROJECT_VERSION = 74;
DEVELOPMENT_TEAM = VL68C36HYS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index f0f66aff..7e82c5b2 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -21,7 +21,7 @@
CFBundleSignature
????
CFBundleVersion
- 73
+ 74
ITSAppUsesNonExemptEncryption
LSRequiresIPhoneOS
diff --git a/lib/core/firebase_api.dart b/lib/core/firebase_api.dart
index 572b56f6..2ba89290 100644
--- a/lib/core/firebase_api.dart
+++ b/lib/core/firebase_api.dart
@@ -6,13 +6,24 @@ import 'package:dio/dio.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/token_storage.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
+import 'package:huawei_push/huawei_push.dart';
class FirebaseApi {
final _firebaseMessaging = FirebaseMessaging.instance;
Future getToken() async {
await _firebaseMessaging.requestPermission();
- return await _firebaseMessaging.getToken();
+
+ String? token = await _firebaseMessaging.getToken();
+
+ if (token == null && Platform.isAndroid) {
+ final isHuawei = await _isHuaweiDevice();
+ if (isHuawei) {
+ token = await _getHuaweiPushToken();
+ }
+ }
+
+ return token;
}
Future registerPushToken() async {
@@ -32,4 +43,38 @@ class FirebaseApi {
}
}
}
+
+ Future _isHuaweiDevice() async {
+ if (!Platform.isAndroid) return false;
+ try {
+ final android = await DeviceInfoPlugin().androidInfo;
+ final brand = android.brand.toLowerCase();
+ final manufacturer = android.manufacturer.toLowerCase();
+ return brand.contains('huawei') || manufacturer.contains('huawei') || brand.contains('honor') || manufacturer.contains('honor');
+ } catch (_) {
+ return false;
+ }
+ }
+
+ Future _getHuaweiPushToken() async {
+ try {
+ await Push.turnOnPush();
+
+ String? resolvedToken;
+ final sub = Push.getTokenStream.listen((t) => resolvedToken ??= t, onError: (_) {});
+
+ Push.getToken('');
+
+ final started = DateTime.now();
+ while (resolvedToken == null && DateTime.now().difference(started).inSeconds < 5) {
+ await Future.delayed(const Duration(milliseconds: 100));
+ }
+
+ await sub.cancel();
+ return resolvedToken;
+ } catch (e, st) {
+ log('Huawei Push token error: $e', stackTrace: st);
+ return null;
+ }
+ }
}
diff --git a/lib/core/theme/theme_helper.dart b/lib/core/theme/theme_helper.dart
index c0c0af29..c202129e 100644
--- a/lib/core/theme/theme_helper.dart
+++ b/lib/core/theme/theme_helper.dart
@@ -204,6 +204,8 @@ class PrimaryColors {
Color get commentBg => const Color(0XFFFFFDD8);
Color get cardNotificationsBG => const Color(0xFFA4A4A4);
+
+ Color get grey7B => const Color(0xFF7B7B7B);
}
PrimaryColors get appTheme => ThemeHelper().themeColor();
diff --git a/lib/features/auth/presentation/pages/auth_screen.dart b/lib/features/auth/presentation/pages/auth_screen.dart
index 8a4e711b..ea457d6c 100644
--- a/lib/features/auth/presentation/pages/auth_screen.dart
+++ b/lib/features/auth/presentation/pages/auth_screen.dart
@@ -1,3 +1,5 @@
+// ignore_for_file: unused_element, duplicate_ignore
+
import 'dart:async';
import 'package:eatvio_app/core/app_router.dart';
import 'package:eatvio_app/core/const.dart';
@@ -365,6 +367,7 @@ class _AuthScreenState extends State {
}
}
+// ignore: unused_element
class _SocialButton extends StatelessWidget {
const _SocialButton({required this.onTap, required this.child, required this.backgroundColor, required this.tooltip});
@@ -391,6 +394,7 @@ class _SocialButton extends StatelessWidget {
}
}
+// ignore: unused_element
void _onVkPressed() async {
final accessToken = await SocialAuthFacade.signInWithVk();
if (accessToken == null) return;
diff --git a/lib/features/blog_post/presentation/cubit/blog_post_cubit.dart b/lib/features/blog_post/presentation/cubit/blog_post_cubit.dart
index 59665002..02196288 100644
--- a/lib/features/blog_post/presentation/cubit/blog_post_cubit.dart
+++ b/lib/features/blog_post/presentation/cubit/blog_post_cubit.dart
@@ -18,4 +18,26 @@ class BlogPostCubit extends Cubit {
emit(state.copyWith(isLoading: false));
}
}
+
+ Future toggleLike() async {
+ final current = state.blogPostModel;
+ if (current == null) return;
+
+ // optimistic update
+ final wasLiked = current.wasLikedByMe;
+ final updated = current.copyWith(wasLikedByMe: !wasLiked, totalLikes: wasLiked ? current.totalLikes - 1 : current.totalLikes + 1);
+ emit(state.copyWith(blogPostModel: updated));
+
+ try {
+ if (wasLiked) {
+ await feedRepository.unlikedBlogPost(id: current.id);
+ } else {
+ await feedRepository.likeBlogPost(id: current.id);
+ }
+ } catch (e, st) {
+ // rollback on error
+ log(e.toString(), stackTrace: st);
+ emit(state.copyWith(blogPostModel: current));
+ }
+ }
}
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 25636a57..61b64f9e 100644
--- a/lib/features/blog_post/presentation/pages/blog_post_screen.dart
+++ b/lib/features/blog_post/presentation/pages/blog_post_screen.dart
@@ -32,8 +32,6 @@ class _BlogPostScreenState extends State {
final CommentsCubit commentsCubit = sl();
final textEditingController = TextEditingController();
int? replyId;
- bool isLiked = false;
- int totalLikes = 0;
@override
void initState() {
@@ -60,26 +58,30 @@ class _BlogPostScreenState extends State {
builder: (BuildContext context, CommentsState state) {
if (blogPostState.isLoading) {
return Scaffold(
- appBar: AppBar(
- leading: BackButton(
- onPressed: () {
- if (context.canPop()) {
- GoRouter.of(context).pop();
- return;
- }
- GoRouter.of(context).go('/feed-screen');
- },
- ),
+ appBar: AppBar(
+ leading: BackButton(
+ onPressed: () {
+ if (context.canPop()) {
+ GoRouter.of(context).pop();
+ return;
+ }
+ GoRouter.of(context).go('/feed-screen');
+ },
),
- body: const Loader());
+ ),
+ body: const Loader(),
+ );
}
- isLiked = blogPostState.blogPostModel?.wasLikedByMe ?? false;
- totalLikes = blogPostState.blogPostModel?.totalLikes ?? 0;
+ final bool isLiked = blogPostState.blogPostModel?.wasLikedByMe ?? false;
+ final int totalLikes = blogPostState.blogPostModel?.totalLikes ?? 0;
return Scaffold(
resizeToAvoidBottomInset: true,
bottomSheet: Container(
padding: const EdgeInsets.symmetric(vertical: 12) + (Platform.isIOS ? const EdgeInsets.only(bottom: 16) : EdgeInsets.zero),
- decoration: BoxDecoration(color: Colors.white, border: Border(top: BorderSide(color: Colors.black.withValues(alpha: 0.1)))),
+ decoration: BoxDecoration(
+ color: Colors.white,
+ border: Border(top: BorderSide(color: Colors.black.withValues(alpha: 0.1))),
+ ),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@@ -114,24 +116,14 @@ class _BlogPostScreenState extends State {
maxLines: 5,
minLines: 1,
keyboardType: TextInputType.multiline,
- style: const TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.w400,
- color: Colors.black,
- height: 1.2,
- ),
+ style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: Colors.black, height: 1.2),
decoration: InputDecoration(
isDense: false,
// убираем true, чтобы padding учитывался корректно
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
// вертикальный паддинг увеличен
hintText: 'Комментарий',
- hintStyle: const TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.w400,
- height: 1.2,
- color: Color(0xFFAEAEB2),
- ),
+ hintStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400, height: 1.2, color: Color(0xFFAEAEB2)),
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
@@ -196,7 +188,7 @@ class _BlogPostScreenState extends State {
id: widget.id,
feedBlogPostModel: blogPostState.blogPostModel,
userSlug: blogPostState.blogPostModel?.author.authorSlug ?? '',
- ),
+ ),
const SizedBox(width: 16),
],
),
@@ -215,9 +207,7 @@ class _BlogPostScreenState extends State {
children: [
CircleAvatar(
radius: 16,
- foregroundImage: NetworkImage(
- baseUrl + (blogPostState.blogPostModel?.author.authorProfileIcon ?? ''),
- ),
+ foregroundImage: NetworkImage(baseUrl + (blogPostState.blogPostModel?.author.authorProfileIcon ?? '')),
backgroundImage: const AssetImage('assets/images/no_avatar.png'),
),
const SizedBox(width: 8),
@@ -242,30 +232,32 @@ class _BlogPostScreenState extends State {
if (blogPostState.blogPostModel?.description.isNotEmpty ?? false)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
- child: Html(data: blogPostState.blogPostModel?.description.replaceAll('\n', '
'), style: {"*": Style(color: Colors.black87)}),
+ child: Html(
+ data: blogPostState.blogPostModel?.description.replaceAll('\n', '
'),
+ style: {"*": Style(color: Colors.black87)},
+ ),
),
const SizedBox(height: 8),
if (blogPostState.blogPostModel?.image.isNotEmpty ?? false)
- CachedNetworkImage(
- imageUrl: '$baseUrl/storage/${blogPostState.blogPostModel?.image ?? ''}',
- ),
+ CachedNetworkImage(imageUrl: '$baseUrl/storage/${blogPostState.blogPostModel?.image ?? ''}'),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
children: [
_iconButton(
- icon: Icons.favorite_border_rounded,
+ icon: isLiked ? Icons.favorite_rounded : Icons.favorite_border_rounded,
text: totalLikes.toString(),
iconColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null,
backgroundColor: isLiked ? Colors.red.withValues(alpha: 0.1) : null,
textColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null,
onTap: () async {
- setState(() {
- isLiked = !isLiked;
- isLiked ? totalLikes++ : totalLikes--;
- });
- isLiked ? await context.read().likePost(widget.id) : await context.read().unlikedPost(widget.id);
- sl().updateFeedBlogPostList(blogPostState.blogPostModel, isLiked);
+ await context.read().toggleLike();
+ // ignore: use_build_context_synchronously
+ final updated = context.read().state.blogPostModel;
+ if (updated != null) {
+ // ignore: use_build_context_synchronously
+ context.read().updateFeedBlogPostList(updated, updated.wasLikedByMe);
+ }
},
),
const SizedBox(width: 8),
@@ -284,8 +276,10 @@ class _BlogPostScreenState extends State {
const Spacer(),
Icon(Icons.visibility_rounded, size: 16, color: appTheme.gray500),
const SizedBox(width: 4),
- Text(blogPostState.blogPostModel?.totalViews.toString() ?? '',
- style: TextStyle(fontSize: 12, color: appTheme.gray500, fontWeight: FontWeight.w400)),
+ Text(
+ blogPostState.blogPostModel?.totalViews.toString() ?? '',
+ style: TextStyle(fontSize: 12, color: appTheme.gray500, fontWeight: FontWeight.w400),
+ ),
],
),
),
@@ -332,7 +326,11 @@ class _BlogPostScreenState extends State {
children: [
Icon(icon, size: 20, color: iconColor ?? appTheme.gray600),
if (text != null) const SizedBox(width: 8),
- if (text != null) Text(text, style: TextStyle(color: textColor ?? appTheme.gray600, fontWeight: FontWeight.w500)),
+ if (text != null)
+ Text(
+ text,
+ style: TextStyle(color: textColor ?? appTheme.gray600, fontWeight: FontWeight.w500),
+ ),
],
),
),
diff --git a/lib/features/consultations/presentation/widgets/consultation_card_widget.dart b/lib/features/consultations/presentation/widgets/consultation_card_widget.dart
index 3d870e8d..f9fa4143 100644
--- a/lib/features/consultations/presentation/widgets/consultation_card_widget.dart
+++ b/lib/features/consultations/presentation/widgets/consultation_card_widget.dart
@@ -1,5 +1,4 @@
import 'package:collection/collection.dart';
-import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/theme/theme_helper.dart';
import 'package:eatvio_app/core/widgets/custom_divider.dart';
@@ -66,7 +65,7 @@ class _ConsultationCardWidgetState extends State {
children: [
Row(
children: [
- CircleAvatar(radius: 30, backgroundImage: NetworkImage(baseUrl + widget.consultationsModel.userProfilePhotoUrl)),
+ CircleAvatar(radius: 30, backgroundImage: NetworkImage(widget.consultationsModel.userProfilePhotoUrl)),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
diff --git a/lib/features/diary/presentation/widgets/mood_rating_widget.dart b/lib/features/diary/presentation/widgets/mood_rating_widget.dart
index 41640b78..d943eac2 100644
--- a/lib/features/diary/presentation/widgets/mood_rating_widget.dart
+++ b/lib/features/diary/presentation/widgets/mood_rating_widget.dart
@@ -23,9 +23,12 @@ class _MoodRatingWidgetState extends State {
builder: (BuildContext context, DiaryState state) {
if (state is DiaryStateLoaded) {
final selectedIndex = state.selectedMeal - 1;
- if (isFirstFetch[selectedIndex]) {
- currentSelectedRating[selectedIndex] = state.diary.meals[selectedIndex].mood.toDouble() + 1;
- isFirstFetch[selectedIndex] = false;
+ final meals = state.diary.meals;
+ if (selectedIndex >= 0 && selectedIndex < meals.length) {
+ if (isFirstFetch[selectedIndex]) {
+ currentSelectedRating[selectedIndex] = meals[selectedIndex].mood.toDouble() + 1;
+ isFirstFetch[selectedIndex] = false;
+ }
}
return Padding(
padding: const EdgeInsets.only(top: 24),
@@ -35,21 +38,17 @@ class _MoodRatingWidgetState extends State {
Text(
state.isConsultantView ? 'Настроение пользователя после приема пищи' : 'Ваше настроение после приёма пищи',
textAlign: TextAlign.center,
- style: const TextStyle(
- fontSize: 16,
- ),
+ style: const TextStyle(fontSize: 16),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- SvgPicture.asset(
- 'assets/icons/mood_1.svg',
- height: 32,
- width: 32,
- ),
+ SvgPicture.asset('assets/icons/mood_1.svg', height: 32, width: 32),
RatingBar.builder(
ignoreGestures: state.isConsultantView || state.isDiaryFinished || state.isDiaryCommented,
- initialRating: state.diary.meals[selectedIndex].mood.toDouble() + 1,
+ initialRating: (selectedIndex >= 0 && selectedIndex < state.diary.meals.length)
+ ? state.diary.meals[selectedIndex].mood.toDouble() + 1
+ : 3,
itemCount: 6,
itemSize: MediaQuery.of(context).size.width / 6 - (124 / 6),
updateOnDrag: true,
@@ -63,20 +62,11 @@ class _MoodRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFFC82222),
border: currentSelectedRating[selectedIndex] == 1
- ? Border.all(
- width: 2,
- color: const Color(0xFFAA3333),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFFAA3333), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 1
- ? const BorderRadius.horizontal(
- left: Radius.circular(8),
- right: Radius.circular(2),
- )
- : const BorderRadius.horizontal(
- left: Radius.circular(8),
- ),
+ ? const BorderRadius.horizontal(left: Radius.circular(8), right: Radius.circular(2))
+ : const BorderRadius.horizontal(left: Radius.circular(8)),
),
);
case 1:
@@ -87,11 +77,7 @@ class _MoodRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFFFF3E3E),
border: currentSelectedRating[selectedIndex] == 2
- ? Border.all(
- width: 2,
- color: const Color(0xFF550000),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFF550000), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 2 ? BorderRadius.circular(2) : null,
),
@@ -104,11 +90,7 @@ class _MoodRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFFF8C926),
border: currentSelectedRating[selectedIndex] == 3
- ? Border.all(
- width: 2,
- color: const Color(0xFF8C5D00),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFF8C5D00), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 3 ? BorderRadius.circular(2) : null,
),
@@ -121,11 +103,7 @@ class _MoodRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFFFFF3BF),
border: currentSelectedRating[selectedIndex] == 4
- ? Border.all(
- width: 2,
- color: const Color(0xFFB5911B),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFFB5911B), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 4 ? BorderRadius.circular(2) : null,
),
@@ -138,11 +116,7 @@ class _MoodRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFF62E833),
border: currentSelectedRating[selectedIndex] == 5
- ? Border.all(
- width: 2,
- color: const Color(0xFF276918),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFF276918), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 5 ? BorderRadius.circular(2) : null,
),
@@ -155,20 +129,11 @@ class _MoodRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFF4DCE20),
border: currentSelectedRating[selectedIndex] == 6
- ? Border.all(
- width: 2,
- color: const Color(0xFF184D12),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFF184D12), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 6
- ? const BorderRadius.horizontal(
- left: Radius.circular(2),
- right: Radius.circular(8),
- )
- : const BorderRadius.horizontal(
- right: Radius.circular(8),
- ),
+ ? const BorderRadius.horizontal(left: Radius.circular(2), right: Radius.circular(8))
+ : const BorderRadius.horizontal(right: Radius.circular(8)),
),
);
}
@@ -177,20 +142,12 @@ class _MoodRatingWidgetState extends State {
setState(() {
currentSelectedRating[selectedIndex] = value;
});
- EasyDebounce.debounce(
- 'change-satiety',
- const Duration(milliseconds: 250),
- () {
- context.read().fillMood(diaryId: state.diary.id, mood: currentSelectedRating[selectedIndex].toInt() - 1);
- },
- );
+ EasyDebounce.debounce('change-satiety', const Duration(milliseconds: 250), () {
+ context.read().fillMood(diaryId: state.diary.id, mood: currentSelectedRating[selectedIndex].toInt() - 1);
+ });
},
),
- SvgPicture.asset(
- 'assets/icons/mood_2.svg',
- height: 32,
- width: 32,
- ),
+ SvgPicture.asset('assets/icons/mood_2.svg', height: 32, width: 32),
],
),
],
diff --git a/lib/features/diary/presentation/widgets/satiety_rating_widget.dart b/lib/features/diary/presentation/widgets/satiety_rating_widget.dart
index d473f691..d36ac75b 100644
--- a/lib/features/diary/presentation/widgets/satiety_rating_widget.dart
+++ b/lib/features/diary/presentation/widgets/satiety_rating_widget.dart
@@ -23,9 +23,12 @@ class _SatietyRatingWidgetState extends State {
builder: (BuildContext context, DiaryState state) {
if (state is DiaryStateLoaded) {
final selectedIndex = state.selectedMeal - 1;
- if (isFirstFetch[selectedIndex]) {
- currentSelectedRating[selectedIndex] = state.diary.meals[selectedIndex].satiety.toDouble() + 1;
- isFirstFetch[selectedIndex] = false;
+ final meals = state.diary.meals;
+ if (selectedIndex >= 0 && selectedIndex < meals.length) {
+ if (isFirstFetch[selectedIndex]) {
+ currentSelectedRating[selectedIndex] = meals[selectedIndex].satiety.toDouble() + 1;
+ isFirstFetch[selectedIndex] = false;
+ }
}
return Padding(
padding: const EdgeInsets.only(top: 24),
@@ -35,21 +38,17 @@ class _SatietyRatingWidgetState extends State {
Text(
state.isConsultantView ? 'Сытость пользователя после приема пищи' : 'Ваша сытость после приёма пищи',
textAlign: TextAlign.center,
- style: const TextStyle(
- fontSize: 16,
- ),
+ style: const TextStyle(fontSize: 16),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- SvgPicture.asset(
- 'assets/icons/satiety_emoji_left.svg',
- height: 32,
- width: 32,
- ),
+ SvgPicture.asset('assets/icons/satiety_emoji_left.svg', height: 32, width: 32),
RatingBar.builder(
ignoreGestures: state.isConsultantView || state.isDiaryFinished || state.isDiaryCommented,
- initialRating: state.diary.meals[selectedIndex].satiety.toDouble() + 1,
+ initialRating: (selectedIndex >= 0 && selectedIndex < state.diary.meals.length)
+ ? state.diary.meals[selectedIndex].satiety.toDouble() + 1
+ : 3,
itemCount: 6,
itemSize: MediaQuery.of(context).size.width / 6 - (124 / 6),
updateOnDrag: true,
@@ -63,20 +62,11 @@ class _SatietyRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFFC82222),
border: currentSelectedRating[selectedIndex] == 1
- ? Border.all(
- width: 2,
- color: const Color(0xFFAA3333),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFFAA3333), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 1
- ? const BorderRadius.horizontal(
- left: Radius.circular(8),
- right: Radius.circular(2),
- )
- : const BorderRadius.horizontal(
- left: Radius.circular(8),
- ),
+ ? const BorderRadius.horizontal(left: Radius.circular(8), right: Radius.circular(2))
+ : const BorderRadius.horizontal(left: Radius.circular(8)),
),
);
case 1:
@@ -87,11 +77,7 @@ class _SatietyRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFFFF3E3E),
border: currentSelectedRating[selectedIndex] == 2
- ? Border.all(
- width: 2,
- color: const Color(0xFF550000),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFF550000), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 2 ? BorderRadius.circular(2) : null,
),
@@ -104,11 +90,7 @@ class _SatietyRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFFF8C926),
border: currentSelectedRating[selectedIndex] == 3
- ? Border.all(
- width: 2,
- color: const Color(0xFF8C5D00),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFF8C5D00), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 3 ? BorderRadius.circular(2) : null,
),
@@ -121,11 +103,7 @@ class _SatietyRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFFFFF3BF),
border: currentSelectedRating[selectedIndex] == 4
- ? Border.all(
- width: 2,
- color: const Color(0xFFB5911B),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFFB5911B), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 4 ? BorderRadius.circular(2) : null,
),
@@ -138,11 +116,7 @@ class _SatietyRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFF62E833),
border: currentSelectedRating[selectedIndex] == 5
- ? Border.all(
- width: 2,
- color: const Color(0xFF276918),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFF276918), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 5 ? BorderRadius.circular(2) : null,
),
@@ -155,20 +129,11 @@ class _SatietyRatingWidgetState extends State {
decoration: BoxDecoration(
color: const Color(0xFF4DCE20),
border: currentSelectedRating[selectedIndex] == 6
- ? Border.all(
- width: 2,
- color: const Color(0xFF184D12),
- strokeAlign: BorderSide.strokeAlignOutside,
- )
+ ? Border.all(width: 2, color: const Color(0xFF184D12), strokeAlign: BorderSide.strokeAlignOutside)
: null,
borderRadius: currentSelectedRating[selectedIndex] == 6
- ? const BorderRadius.horizontal(
- left: Radius.circular(2),
- right: Radius.circular(8),
- )
- : const BorderRadius.horizontal(
- right: Radius.circular(8),
- ),
+ ? const BorderRadius.horizontal(left: Radius.circular(2), right: Radius.circular(8))
+ : const BorderRadius.horizontal(right: Radius.circular(8)),
),
);
}
@@ -178,20 +143,12 @@ class _SatietyRatingWidgetState extends State {
setState(() {
currentSelectedRating[selectedIndex] = value;
});
- EasyDebounce.debounce(
- 'change-satiety',
- const Duration(milliseconds: 250),
- () {
- context.read().fillSatiety(diaryId: state.diary.id, satiety: currentSelectedRating[selectedIndex].toInt() - 1);
- },
- );
+ EasyDebounce.debounce('change-satiety', const Duration(milliseconds: 250), () {
+ context.read().fillSatiety(diaryId: state.diary.id, satiety: currentSelectedRating[selectedIndex].toInt() - 1);
+ });
},
),
- SvgPicture.asset(
- 'assets/icons/satiety_emoji_right.svg',
- height: 32,
- width: 32,
- ),
+ SvgPicture.asset('assets/icons/satiety_emoji_right.svg', height: 32, width: 32),
],
),
],
diff --git a/lib/features/diary/repositories/diary_repository.dart b/lib/features/diary/repositories/diary_repository.dart
index 0165ad7f..f3ff8bb5 100644
--- a/lib/features/diary/repositories/diary_repository.dart
+++ b/lib/features/diary/repositories/diary_repository.dart
@@ -82,7 +82,53 @@ class DiaryRepository {
}
Future getDiaryDay(int diaryId) async {
- return (await diaryService.getDiaryDay(diary: diaryId)).diary;
+ // Align with getDiaryByDate: enrich portions with glossary nutritional info
+ final diaryWrapper = await diaryService.getDiaryDay(diary: diaryId);
+ final DiaryDayModel diaryDay = diaryWrapper.diary;
+ Set ids = {};
+ for (var meal in diaryDay.meals) {
+ for (var portion in meal.portions) {
+ if (portion.productNutritionalValueId != null) {
+ ids.add(portion.productNutritionalValueId!);
+ }
+ }
+ }
+ if (ids.isNotEmpty) {
+ final glossary = await getGlossariesIndex(ids: ids.toList());
+ final List updatedMeals = List.from(diaryDay.meals);
+ for (var mealIndex = 0; mealIndex < updatedMeals.length; mealIndex++) {
+ final meal = updatedMeals[mealIndex];
+ final updatedPortions = meal.portions.map((portion) {
+ if (portion.productNutritionalValueId != null) {
+ try {
+ final glossaryItem = glossary.glossariesList.firstWhere((g) => g.id == portion.productNutritionalValueId);
+ return portion.copyWith(
+ productCaloriesInfo: ProductCaloriesInfoModel(
+ id: glossaryItem.id,
+ productName: glossaryItem.name,
+ calories: glossaryItem.energyOn100Gr,
+ proteins: glossaryItem.proteinsOn100Gr,
+ fats: glossaryItem.fatsOn100Gr,
+ carbohydrates: glossaryItem.carbohydratesOn100Gr,
+ energyOnPortion: glossaryItem.energyOnPortion,
+ proteinsOnPortion: glossaryItem.proteinsOnPortion,
+ fatsOnPortion: glossaryItem.fatsOnPortion,
+ carbohydratesOnPortion: glossaryItem.carbohydratesOnPortion,
+ ),
+ );
+ } catch (e) {
+ return portion;
+ }
+ }
+ return portion;
+ }).toList();
+
+ updatedMeals[mealIndex] = meal.copyWith(portions: updatedPortions);
+ }
+ final updatedDiaryDay = diaryDay.copyWith(meals: updatedMeals);
+ return updatedDiaryDay;
+ }
+ return diaryDay;
}
Future getNutritionData(int index) async {
diff --git a/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart b/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart
index 947b9a5d..d1bf399f 100644
--- a/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart
+++ b/lib/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart
@@ -15,13 +15,12 @@ class FeedCubit extends Cubit {
FeedCubit({required this.feedRepository}) : super(const FeedState.loading());
void updateFeedBlogPostList(FeedBlogPostModel? feedBlogPostModel, bool wasLikedByMe) {
- if (feedBlogPostModel == null || isClosed) return;
- List feedBlogPostList = [...(state as FeedStateLoaded).feedBlogPostList];
- final int index = feedBlogPostList.indexOf(feedBlogPostModel);
- feedBlogPostList[index] = feedBlogPostModel.copyWith(
- wasLikedByMe: wasLikedByMe,
- totalLikes: wasLikedByMe == false ? feedBlogPostList[index].totalLikes - 1 : feedBlogPostList[index].totalLikes + 1,
- );
+ if (feedBlogPostModel == null || isClosed || state is! FeedStateLoaded) return;
+ final List feedBlogPostList = [...(state as FeedStateLoaded).feedBlogPostList];
+ final int index = feedBlogPostList.indexWhere((e) => e.id == feedBlogPostModel.id);
+ if (index == -1) return;
+ final current = feedBlogPostList[index];
+ feedBlogPostList[index] = current.copyWith(wasLikedByMe: wasLikedByMe, totalLikes: wasLikedByMe ? current.totalLikes + 1 : current.totalLikes - 1);
if (!isClosed) {
emit(FeedState.loaded(feedBlogPostList: feedBlogPostList, isLoading: isLoading));
}
@@ -81,5 +80,4 @@ class FeedCubit extends Cubit {
Future viewRecipe(String slug) async => await feedRepository.viewRecipe(slug);
Future viewDiet(int id) async => await feedRepository.viewDiet(id);
Future viewPlan(String slug) async => await feedRepository.viewPlan(slug);
-
}
diff --git a/lib/features/feed/presentation/pages/feed_screen.dart b/lib/features/feed/presentation/pages/feed_screen.dart
index 844788fe..796b4a3b 100644
--- a/lib/features/feed/presentation/pages/feed_screen.dart
+++ b/lib/features/feed/presentation/pages/feed_screen.dart
@@ -36,7 +36,6 @@ class FeedScreen extends StatelessWidget {
providers: [
BlocProvider(create: (context) => sl()..loadRecipesList()),
BlocProvider(create: (context) => sl()..getProfile()),
- BlocProvider(create: (context) => sl()..loadFeedBlogPostList()),
BlocProvider(create: (context) => sl()..loadDiets()),
if (!hidePlans) BlocProvider(create: (context) => sl()..loadPlans()),
BlocProvider(create: (context) => sl()..getConsultants()),
@@ -78,8 +77,6 @@ class _FeedScreenContentState extends State {
if (consultantsScrollController.offset >= consultantsScrollController.position.maxScrollExtent && !consultantsScrollController.position.outOfRange) {}
}
-
-
@override
void dispose() {
blogPostsScrollController.dispose();
@@ -90,8 +87,6 @@ class _FeedScreenContentState extends State {
super.dispose();
}
-
-
@override
Widget build(BuildContext context) {
FlutterNativeSplash.remove();
diff --git a/lib/features/feed/presentation/widgets/blog_post_widget.dart b/lib/features/feed/presentation/widgets/blog_post_widget.dart
index 23eaeded..e001a038 100644
--- a/lib/features/feed/presentation/widgets/blog_post_widget.dart
+++ b/lib/features/feed/presentation/widgets/blog_post_widget.dart
@@ -21,10 +21,7 @@ import 'package:share_plus/share_plus.dart';
class BlogPostWidget extends StatefulWidget {
final int index;
- const BlogPostWidget({
- super.key,
- required this.index,
- });
+ const BlogPostWidget({super.key, required this.index});
@override
State createState() => _BlogPostWidgetState();
@@ -44,10 +41,7 @@ class _BlogPostWidgetState extends State {
totalLikes = state.feedBlogPostList[widget.index].totalLikes;
return InkWell(
borderRadius: BorderRadius.circular(12),
- onTap: () => GoRouter.of(context).pushNamed(
- 'blogPostScreen',
- extra: state.feedBlogPostList[widget.index].id,
- ),
+ onTap: () => GoRouter.of(context).pushNamed('blogPostScreen', extra: state.feedBlogPostList[widget.index].id),
child: Material(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
@@ -95,21 +89,12 @@ class _BlogPostWidgetState extends State {
Text(
state.feedBlogPostList[widget.index].author.authorName,
overflow: TextOverflow.ellipsis,
- style: const TextStyle(
- height: 1,
- color: Colors.black87,
- fontWeight: FontWeight.w500,
- fontSize: 16,
- ),
+ style: const TextStyle(height: 1, color: Colors.black87, fontWeight: FontWeight.w500, fontSize: 16),
),
const SizedBox(height: 4),
Text(
'${calculateDifference(state.feedBlogPostList[widget.index].createdAt)} в ${state.feedBlogPostList[widget.index].createdAt.hour.toString().padLeft(2, '0')}:${state.feedBlogPostList[widget.index].createdAt.minute.toString().padLeft(2, '0')}',
- style: const TextStyle(
- height: 1,
- color: Colors.black45,
- fontSize: 14,
- ),
+ style: const TextStyle(height: 1, color: Colors.black45, fontSize: 14),
),
],
),
@@ -119,9 +104,7 @@ class _BlogPostWidgetState extends State {
!state.feedBlogPostList[widget.index].author.authorIsMe)
Padding(
padding: const EdgeInsets.only(right: 8),
- child: SubscribeButtonWidget(
- slug: state.feedBlogPostList[widget.index].author.authorSlug,
- ),
+ child: SubscribeButtonWidget(slug: state.feedBlogPostList[widget.index].author.authorSlug),
),
// Кнопка меню
CustomPopup(
@@ -141,11 +124,7 @@ class _BlogPostWidgetState extends State {
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text(
state.feedBlogPostList[widget.index].title,
- style: const TextStyle(
- fontSize: 18,
- fontWeight: FontWeight.w600,
- color: Colors.black87,
- ),
+ style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Colors.black87),
),
),
],
@@ -156,15 +135,12 @@ class _BlogPostWidgetState extends State {
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Html(
- data: (state.feedBlogPostList[widget.index].description.length > 200
- ? state.feedBlogPostList[widget.index].description.substring(0, 200)
- : state.feedBlogPostList[widget.index].description).replaceAll('\n', '
'),
- style: {
- "*": Style(
- fontSize: FontSize(16),
- color: Colors.black87,
- ),
- },
+ data:
+ (state.feedBlogPostList[widget.index].description.length > 200
+ ? state.feedBlogPostList[widget.index].description.substring(0, 200)
+ : state.feedBlogPostList[widget.index].description)
+ .replaceAll('\n', '
'),
+ style: {"*": Style(fontSize: FontSize(16), color: Colors.black87)},
),
),
if (state.feedBlogPostList[widget.index].description.length > 200)
@@ -172,12 +148,7 @@ class _BlogPostWidgetState extends State {
padding: EdgeInsets.symmetric(horizontal: 12),
child: Text(
'Показать ещё',
- style: TextStyle(
- height: 1,
- color: Color(0xFF8B8B8B),
- fontSize: 14,
- fontWeight: FontWeight.w600,
- ),
+ style: TextStyle(height: 1, color: Color(0xFF8B8B8B), fontSize: 14, fontWeight: FontWeight.w600),
),
),
if (state.feedBlogPostList[widget.index].title.isNotEmpty || state.feedBlogPostList[widget.index].description.isNotEmpty)
@@ -186,10 +157,7 @@ class _BlogPostWidgetState extends State {
onTap: () {
context.pushTransparentRoute(
rootNavigator: true,
- PhotoViewScreen(
- imageUrls: ['$baseUrl/storage/${state.feedBlogPostList[widget.index].image}'],
- index: 0,
- ),
+ PhotoViewScreen(imageUrls: ['$baseUrl/storage/${state.feedBlogPostList[widget.index].image}'], index: 0),
);
},
child: Hero(
@@ -218,11 +186,14 @@ class _BlogPostWidgetState extends State {
isLiked = !isLiked;
isLiked ? totalLikes++ : totalLikes--;
});
- isLiked
- ? await context.read().likePost(state.feedBlogPostList[widget.index].id)
- : await context.read().unlikedPost(state.feedBlogPostList[widget.index].id);
- if (!context.mounted) return;
- await context.read().loadFeedBlogPostList();
+ // Update feed list immediately by ID (no reload)
+ context.read().updateFeedBlogPostList(state.feedBlogPostList[widget.index], isLiked);
+ // Fire network call without introducing UI delay
+ if (isLiked) {
+ await context.read().likePost(state.feedBlogPostList[widget.index].id);
+ } else {
+ await context.read().unlikedPost(state.feedBlogPostList[widget.index].id);
+ }
},
),
const SizedBox(width: 8),
@@ -231,16 +202,10 @@ class _BlogPostWidgetState extends State {
'assets/icons/comment.svg',
height: 20,
width: 20,
- colorFilter: ColorFilter.mode(
- appTheme.gray600,
- BlendMode.srcIn,
- ),
+ colorFilter: ColorFilter.mode(appTheme.gray600, BlendMode.srcIn),
),
text: state.feedBlogPostList[widget.index].totalComments.toString(),
- onTap: () => GoRouter.of(context).pushNamed(
- 'blogPostScreen',
- extra: state.feedBlogPostList[widget.index].id,
- ),
+ onTap: () => GoRouter.of(context).pushNamed('blogPostScreen', extra: state.feedBlogPostList[widget.index].id),
),
const SizedBox(width: 8),
FeedIconButton(
@@ -254,28 +219,18 @@ class _BlogPostWidgetState extends State {
final box = context.findRenderObject() as RenderBox?;
SharePlus.instance.share(
ShareParams(
- uri: Uri.parse(
- '$baseUrl/ru/blog_post/${state.feedBlogPostList[widget.index].id}',
- ),
+ uri: Uri.parse('$baseUrl/ru/blog_post/${state.feedBlogPostList[widget.index].id}'),
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
),
);
},
),
const Spacer(),
- Icon(
- Icons.visibility_rounded,
- size: 16,
- color: appTheme.gray500,
- ),
+ Icon(Icons.visibility_rounded, size: 16, color: appTheme.gray500),
const SizedBox(width: 4),
Text(
state.feedBlogPostList[widget.index].totalViews.toString(),
- style: TextStyle(
- fontSize: 12,
- color: appTheme.gray500,
- fontWeight: FontWeight.w400,
- ),
+ style: TextStyle(fontSize: 12, color: appTheme.gray500, fontWeight: FontWeight.w400),
),
],
),
diff --git a/lib/features/profile/models/profile_model.dart b/lib/features/profile/models/profile_model.dart
index 03fd57f3..17eaa671 100644
--- a/lib/features/profile/models/profile_model.dart
+++ b/lib/features/profile/models/profile_model.dart
@@ -19,6 +19,7 @@ abstract class ProfileModel with _$ProfileModel {
@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_blocked_by_author", fromJson: parseBool) required bool isBlockedByAuthor,
@JsonKey(name: "is_blocked_by_user", fromJson: parseBool, defaultValue: false) required bool isBlockedByUser,
@JsonKey(name: 'is_entity_subscribed_by_me') required bool isEntitySubscribedByMe,
@JsonKey(name: "slug") required String slug,
diff --git a/lib/features/profile/presentation/pages/profile_screen.dart b/lib/features/profile/presentation/pages/profile_screen.dart
index 98966234..11ae9b7a 100644
--- a/lib/features/profile/presentation/pages/profile_screen.dart
+++ b/lib/features/profile/presentation/pages/profile_screen.dart
@@ -5,6 +5,7 @@ import 'package:eatvio_app/core/app_router.dart';
import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/enums/complained_content.dart';
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
+import 'package:eatvio_app/core/theme/custom_text_style.dart';
import 'package:eatvio_app/core/utils/date_time_utils.dart';
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
import 'package:eatvio_app/core/widgets/loader.dart';
@@ -93,30 +94,6 @@ class _ProfileScreenState extends State {
isFirstFetch = false;
}
- // Проверяем, заблокировал ли пользователь меня
- if (state.profile.isBlockedByUser) {
- return Scaffold(
- appBar: AppBar(),
- body: Center(
- child: Padding(
- padding: const EdgeInsets.all(32.0),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Icon(Icons.block, size: 64, color: Colors.grey[400]),
- const SizedBox(height: 16),
- Text(
- 'Пользователь ограничил доступ к своей странице',
- textAlign: TextAlign.center,
- style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500, color: Colors.grey[600]),
- ),
- ],
- ),
- ),
- ),
- );
- }
-
return widget.author == null || widget.author!.authorIsMe ? _myProfileScreen(state) : _profileScreen(state);
} else if (state is ProfileStateError) {
return Scaffold(
@@ -198,11 +175,34 @@ class _ProfileScreenState extends State {
),
_subscriptionsAndSubscribers(state),
if (state.profile.badges.isNotEmpty) Padding(padding: const EdgeInsets.only(bottom: 16), child: _badges(state)),
- if (state.profile.roles.contains('consultant') && state.consultantInfo != null && !state.profile.isBlockedByMe) _socialLinks(state),
- if (state.profile.roles.contains('consultant') && state.consultantInfo != null && !state.profile.isBlockedByMe) _education(state),
- if (state.profile.roles.contains('consultant') && state.consultantInfo != null && !state.profile.isBlockedByMe) _diplomasAndCertificates(state),
- if (state.profile.roles.contains('consultant') && state.consultantInfo != null && !hidePlans && !state.profile.isBlockedByMe) _activePlans(state),
- if (state.blogPosts.isNotEmpty)
+ if (state.profile.isBlockedByAuthor)
+ Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Icon(Icons.block, size: 48, color: appTheme.grey7B),
+ const SizedBox(height: 16),
+ Center(
+ child: Text(
+ 'Пользователь ограничил доступ\nк своей странице',
+ textAlign: TextAlign.center,
+ style: TextStyles.textMSemibold.copyWith(color: appTheme.grey7B),
+ ),
+ ),
+ ],
+ ),
+ if (state.profile.roles.contains('consultant') && state.consultantInfo != null && !state.profile.isBlockedByMe && !state.profile.isBlockedByAuthor)
+ _socialLinks(state),
+ if (state.profile.roles.contains('consultant') && state.consultantInfo != null && !state.profile.isBlockedByMe && !state.profile.isBlockedByAuthor)
+ _education(state),
+ if (state.profile.roles.contains('consultant') && state.consultantInfo != null && !state.profile.isBlockedByMe && !state.profile.isBlockedByAuthor)
+ _diplomasAndCertificates(state),
+ if (state.profile.roles.contains('consultant') &&
+ state.consultantInfo != null &&
+ !hidePlans &&
+ !state.profile.isBlockedByMe &&
+ !state.profile.isBlockedByAuthor)
+ _activePlans(state),
+ if (state.blogPosts.isNotEmpty && !state.profile.isBlockedByAuthor && !state.profile.isBlockedByMe)
const Padding(
padding: EdgeInsets.only(left: 8, top: 16, bottom: 8),
child: Text(
@@ -210,7 +210,7 @@ class _ProfileScreenState extends State {
style: TextStyle(color: Color(0xFF323F4B), fontSize: 24, fontWeight: FontWeight.w600),
),
),
- _blogPosts(state),
+ if (state.blogPosts.isNotEmpty && !state.profile.isBlockedByAuthor && !state.profile.isBlockedByMe) _blogPosts(state),
],
),
),
diff --git a/lib/features/user_details/presentation/user_details_screen.dart b/lib/features/user_details/presentation/user_details_screen.dart
index 4907e3dd..46e986f4 100644
--- a/lib/features/user_details/presentation/user_details_screen.dart
+++ b/lib/features/user_details/presentation/user_details_screen.dart
@@ -231,7 +231,7 @@ class _UserDetailsContentState extends State {
children: [
Text(s.has_hypo, style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
const SizedBox(height: 4),
- CustomTextFormField(readOnly: true, controller: TextEditingController(text: profileDetails.hasHypo.toString())),
+ CustomTextFormField(readOnly: true, controller: TextEditingController(text: profileDetails.hasHypo ? 'да' : 'нет')),
],
),
),
@@ -242,7 +242,7 @@ class _UserDetailsContentState extends State {
children: [
Text(s.has_hyper, style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
const SizedBox(height: 4),
- CustomTextFormField(readOnly: true, controller: TextEditingController(text: profileDetails.hasHyper.toString())),
+ CustomTextFormField(readOnly: true, controller: TextEditingController(text: profileDetails.hasHyper ? 'да' : 'нет')),
],
),
),
diff --git a/pubspec.yaml b/pubspec.yaml
index 6861a603..3f1e036e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: eatvio_app
description: A new Flutter project.
-version: 1.2.13+73
+version: 1.2.14+74
publish_to: 'none'
environment:
@@ -74,6 +74,7 @@ dependencies:
flutter_dotenv: ^5.2.1
uuid: ^4.5.1
appmetrica_plugin: ^3.3.0
+ huawei_push: ^6.11.0+300
dev_dependencies:
build_runner: ^2.7.0
diff --git a/test/features/profile/services/profile_service_test.dart b/test/features/profile/services/profile_service_test.dart
index 8c666344..5c773bc3 100644
--- a/test/features/profile/services/profile_service_test.dart
+++ b/test/features/profile/services/profile_service_test.dart
@@ -30,6 +30,7 @@ void main() {
badges: [],
subscriptions: [],
subscribers: [],
+ isBlockedByAuthor: false,
),
),
);
@@ -72,23 +73,17 @@ void main() {
});
test('getBlogPostByAuthorSlug', () async {
- when(mockProfileService.getBlogPostByAuthorSlug(slug: '')).thenAnswer(
- (_) async => [],
- );
+ when(mockProfileService.getBlogPostByAuthorSlug(slug: '')).thenAnswer((_) async => []);
expect(await mockProfileService.getBlogPostByAuthorSlug(slug: 'slug'), isA>());
});
test('getWeight', () async {
- when(mockProfileService.getWeight(period: '')).thenAnswer(
- (_) async => [],
- );
+ when(mockProfileService.getWeight(period: '')).thenAnswer((_) async => []);
expect(await mockProfileService.getWeight(period: ''), isA>());
});
test('getCircumferences', () async {
- when(mockProfileService.getCircumferences(period: '')).thenAnswer(
- (_) async => [],
- );
+ when(mockProfileService.getCircumferences(period: '')).thenAnswer((_) async => []);
expect(await mockProfileService.getCircumferences(period: ''), isA>());
});
});