From bd9aedb5deaa9e84d78e8c84432ac41cfc43fee3 Mon Sep 17 00:00:00 2001 From: kishan Date: Thu, 8 Aug 2024 18:45:38 +0530 Subject: [PATCH] comment tree completed --- ios/Podfile.lock | 6 + lib/Common/ApiRepositoy.dart | 18 + lib/Common/api_urls.dart | 7 + lib/Common/controller/MainScreen.dart | 4 +- lib/Global.dart | 2 + .../Community_HomePage/Community.dart | 2 +- .../Model/NestedCommentsModel.dart | 101 ++ .../View/PostDetailScreen.dart | 913 ++++++++++++------ .../ViewModel/CommentsHelper.dart | 5 + .../ViewModel/CommentsRepository.dart | 51 + lib/Utils/Common/CustomTextformfield.dart | 13 +- lib/main.dart | 6 +- .../Signup/view_model/getUserprofile.dart | 5 + pubspec.lock | 48 + pubspec.yaml | 1 + 15 files changed, 879 insertions(+), 303 deletions(-) create mode 100644 lib/Common/ApiRepositoy.dart create mode 100644 lib/Main_Screens/Community_HomePage/PostDetailScreen/Model/NestedCommentsModel.dart create mode 100644 lib/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsHelper.dart create mode 100644 lib/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsRepository.dart diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 6e5bb08..2bd5b2c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -82,6 +82,8 @@ PODS: - flutter_facebook_auth (6.0.4): - FBSDKLoginKit (~> 16.3.1) - Flutter + - flutter_keyboard_visibility (0.0.1): + - Flutter - fluttertoast (0.0.2): - Flutter - Toast @@ -169,6 +171,7 @@ DEPENDENCIES: - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - Flutter (from `Flutter`) - flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`) + - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`) - google_maps_flutter_ios (from `.symlinks/plugins/google_maps_flutter_ios/ios`) @@ -222,6 +225,8 @@ EXTERNAL SOURCES: :path: Flutter flutter_facebook_auth: :path: ".symlinks/plugins/flutter_facebook_auth/ios" + flutter_keyboard_visibility: + :path: ".symlinks/plugins/flutter_keyboard_visibility/ios" fluttertoast: :path: ".symlinks/plugins/fluttertoast/ios" geolocator_apple: @@ -265,6 +270,7 @@ SPEC CHECKSUMS: FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_facebook_auth: c8700ab1770f3d8e5e7456220e4f3bbcdb831454 + flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 fluttertoast: 9f2f8e81bb5ce18facb9748d7855bf5a756fe3db geolocator_apple: 6cbaf322953988e009e5ecb481f07efece75c450 google_maps_flutter_ios: d1318b4ff711612cab16862d7a87e31a7403d458 diff --git a/lib/Common/ApiRepositoy.dart b/lib/Common/ApiRepositoy.dart new file mode 100644 index 0000000..a34f525 --- /dev/null +++ b/lib/Common/ApiRepositoy.dart @@ -0,0 +1,18 @@ +// import 'package:get/get.dart'; +// import 'package:flutter/material.dart'; +// import 'package:async/async.dart'; +// import 'package:regroup/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsRepository.dart'; +// class ApiRepository extends GetxController { +// Future> fetchMultipleAPIs() async { +// FutureGroup futureGroup = FutureGroup(); +// // PostDetail +// futureGroup.add(CommentsRepository().getAllComments()); + + +// // Close the group (no more futures can be added) +// futureGroup.close(); + +// // Wait for all futures to complete +// return await futureGroup.future; +// } +// } diff --git a/lib/Common/api_urls.dart b/lib/Common/api_urls.dart index 7811efc..4107f36 100644 --- a/lib/Common/api_urls.dart +++ b/lib/Common/api_urls.dart @@ -125,4 +125,11 @@ class ApiUrls { static const getuserpinlist = "${baseUrl}fetch-pinned-detail"; static const postusertag = "${baseUrl}pin-unpin"; + + //comments + static const getComments = "${baseUrl}fetch-comment-with-replied-comment"; + static const storeComments = "${baseUrl}store-comment"; + static const storeRepliesOnComments = "${baseUrl}reply-on-comment"; + static const deleteComments = "${baseUrl}delete-comment"; + static const deleteRepliesComments = "${baseUrl}delete-reply-on-comment"; } diff --git a/lib/Common/controller/MainScreen.dart b/lib/Common/controller/MainScreen.dart index 87a871f..c14ddc3 100644 --- a/lib/Common/controller/MainScreen.dart +++ b/lib/Common/controller/MainScreen.dart @@ -4,9 +4,7 @@ import 'package:get/get.dart'; import 'package:regroup/Common/controller/MainController.dart'; import 'package:regroup/Main_Screens/ProfileTab/EditProfile/ViewModel/InterestApiList.dart'; - final MainController mainController = Get.put(MainController()); - class MainScreen extends StatefulWidget { const MainScreen({super.key}); @@ -15,10 +13,10 @@ class MainScreen extends StatefulWidget { } class _MainScreenState extends State { - @override void initState() { InterestListApi().getinterestlistApi(); + super.initState(); } diff --git a/lib/Global.dart b/lib/Global.dart index 665a8cf..dc71b9e 100644 --- a/lib/Global.dart +++ b/lib/Global.dart @@ -15,5 +15,7 @@ late Timer timerhomeglobal; bool isTimerInitialize = false; String? globalAccountType; String? mainWelcomeName; +String userIdGlobal = "0"; + diff --git a/lib/Main_Screens/Community_HomePage/Community.dart b/lib/Main_Screens/Community_HomePage/Community.dart index 4e8ef80..c6ef975 100644 --- a/lib/Main_Screens/Community_HomePage/Community.dart +++ b/lib/Main_Screens/Community_HomePage/Community.dart @@ -343,7 +343,7 @@ Widget normalcardtile2({ } } - return commonGlassUI( + return commonGlassUI( width: double.infinity, height: 760.h, mainOpacity: 1, diff --git a/lib/Main_Screens/Community_HomePage/PostDetailScreen/Model/NestedCommentsModel.dart b/lib/Main_Screens/Community_HomePage/PostDetailScreen/Model/NestedCommentsModel.dart new file mode 100644 index 0000000..596cf7d --- /dev/null +++ b/lib/Main_Screens/Community_HomePage/PostDetailScreen/Model/NestedCommentsModel.dart @@ -0,0 +1,101 @@ +class NestedCommentsModel { + NestedCommentsModel({ + required this.status, + required this.statusCode, + required this.message, + required this.data, + }); + + final String? status; + final int? statusCode; + final String? message; + final List data; + + factory NestedCommentsModel.fromJson(Map json){ + return NestedCommentsModel( + status: json["status"], + statusCode: json["status_code"], + message: json["message"], + data: json["data"] == null ? [] : List.from(json["data"]!.map((x) => Datum.fromJson(x))), + ); + } + +} + +class Datum { + Datum({ + required this.id, + required this.managePostsXid, + required this.iamPrincipalXid, + required this.comment, + required this.userDetail, + required this.repliedComment, + }); + + final int? id; + final int? managePostsXid; + final int? iamPrincipalXid; + final String? comment; + final UserDetail? userDetail; + final List repliedComment; + + factory Datum.fromJson(Map json){ + return Datum( + id: json["id"], + managePostsXid: json["manage_posts_xid"], + iamPrincipalXid: json["iam_principal_xid"], + comment: json["comment"], + userDetail: json["user_detail"] == null ? null : UserDetail.fromJson(json["user_detail"]), + repliedComment: json["replied_comment"] == null ? [] : List.from(json["replied_comment"]!.map((x) => RepliedComment.fromJson(x))), + ); + } + +} + +class RepliedComment { + RepliedComment({ + required this.id, + required this.postsMasterCommentXid, + required this.iamPrincipalXid, + required this.comment, + required this.userDetail, + }); + + final int? id; + final int? postsMasterCommentXid; + final int? iamPrincipalXid; + final String? comment; + final UserDetail? userDetail; + + factory RepliedComment.fromJson(Map json){ + return RepliedComment( + id: json["id"], + postsMasterCommentXid: json["posts_master_comment_xid"], + iamPrincipalXid: json["iam_principal_xid"], + comment: json["comment"], + userDetail: json["user_detail"] == null ? null : UserDetail.fromJson(json["user_detail"]), + ); + } + +} + +class UserDetail { + UserDetail({ + required this.id, + required this.userName, + required this.profilePhoto, + }); + + final int? id; + final String? userName; + final String? profilePhoto; + + factory UserDetail.fromJson(Map json){ + return UserDetail( + id: json["id"], + userName: json["user_name"], + profilePhoto: json["profile_photo"], + ); + } + +} diff --git a/lib/Main_Screens/Community_HomePage/PostDetailScreen/View/PostDetailScreen.dart b/lib/Main_Screens/Community_HomePage/PostDetailScreen/View/PostDetailScreen.dart index b4eccee..10a3f81 100644 --- a/lib/Main_Screens/Community_HomePage/PostDetailScreen/View/PostDetailScreen.dart +++ b/lib/Main_Screens/Community_HomePage/PostDetailScreen/View/PostDetailScreen.dart @@ -1,16 +1,25 @@ import 'package:comment_tree/comment_tree.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:flutter_reaction_button/flutter_reaction_button.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:get/get_state_manager/get_state_manager.dart'; import 'package:regroup/Common/CommonGlassmorphism.dart'; import 'package:regroup/Common/CommonWidget.dart'; +import 'package:regroup/Common/base_manager.dart'; +import 'package:regroup/Global.dart'; +import 'package:regroup/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsHelper.dart'; +import 'package:regroup/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsRepository.dart'; import 'package:regroup/Utils/Common/CommonAppbar.dart'; import 'package:regroup/Utils/Common/CustomTextformfield.dart'; import 'package:regroup/Utils/Common/sized_box.dart'; import 'package:regroup/Utils/texts.dart'; import 'package:regroup/resources/routes/route_name.dart'; +import 'package:async/async.dart'; class PostDetailsScreen extends StatefulWidget { const PostDetailsScreen({super.key}); @@ -20,301 +29,632 @@ class PostDetailsScreen extends StatefulWidget { } class _PostDetailsScreenState extends State { - List _hideReplies = List.filled(5, true); + List hideReplies = []; + FutureGroup futureGroup = FutureGroup(); + final FocusNode _focusNode = FocusNode(); + final TextEditingController _controllerComments = TextEditingController(); + final CommentsHelper _commentsHelper = Get.put(CommentsHelper()); + + @override + void initState() { + futureGroup.add(CommentsRepository().getAllComments()); + futureGroup.close(); + super.initState(); + } + + bool isOnce = true; + _setViewMoreList() { + if (isOnce) { + hideReplies = List.filled(nestedComments!.data.length, false); + isOnce = false; + } + } + + _toggleReplies(index) { + setState(() { + hideReplies[index] = !hideReplies[index]; + }); + } + + void _focusTextField() { + FocusScope.of(context).requestFocus(_focusNode); + } + + _postComments() async { + var updata = { + "manage_posts_xid": "1", + "comment": _controllerComments.text, + }; + final result = await CommentsRepository().postComments(updata); + if (result.status == ResponseStatus.SUCCESS) { + CommentsRepository().getAllComments().then((value) => setState(() { + isOnce = true; + _commentsHelper.isLoading.value = false; + _controllerComments.clear(); + })); + } + } + + String repliedCommentId = ""; + _postRepliesOnComment(repliedCommentId) async { + var updata = { + "manage_posts_xid": "1", + "posts_master_comment_xid": repliedCommentId, + "comment": _controllerComments.text, + }; + final result = await CommentsRepository().postRepliesOnComments(updata); + if (result.status == ResponseStatus.SUCCESS) { + CommentsRepository().getAllComments().then((value) => setState(() { + isOnce = true; + _commentsHelper.isLoading.value = false; + _controllerComments.clear(); + })); + } + } + // _setComments(index) { + // List repliedCommentsList = []; + // for (var i = 0; + // i < nestedComments!.data[index].repliedComment.length; + // i++) { + // repliedCommentsList.add(Comment( + // avatar: nestedComments! + // .data[index].repliedComment[i].userDetail?.profilePhoto, + // userName: nestedComments! + // .data[index].repliedComment[i].userDetail?.userName, + // content: nestedComments!.data[index].repliedComment[i].comment)); + // } + // return repliedCommentsList; + // } + // bool _hideReplies = true; + _deleteComment(String commentId) async { + var updata = {"id": commentId}; + final result = await CommentsRepository().deleteComments(updata); + if (result.status == ResponseStatus.SUCCESS) { + CommentsRepository().getAllComments().then((value) => setState(() { + isOnce = true; + })); + } + } + + _deleteRepliedComment(String commentId) async { + var updata = {"id": commentId}; + final result = await CommentsRepository().deleteRepliedComments(updata); + if (result.status == ResponseStatus.SUCCESS) { + CommentsRepository().getAllComments().then((value) => setState(() { + isOnce = true; + })); + } + } + @override Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomInset: false, - backgroundColor: const Color(0xFF222935), - extendBody: true, - appBar: const CommonAppbar( - titleTxt: "Post", - ), - body: Stack(children: [ - Container( - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/images/png/Ellipse 1496.png"), - fit: BoxFit.fill)), + return KeyboardVisibilityBuilder(builder: (context, isKeyboardVisible) { + return Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: const Color(0xFF222935), + extendBody: true, + appBar: const CommonAppbar( + titleTxt: "Post", ), - SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - postCards( - profileImg: 'assets/images/png/Ellipse 52.png', - title: 'Ryan Dorwat', - mainImg: 'assets/images/png/Rectangle 25.png', - containerTitle: [ - 'Football', - 'Marathon', - 'Events', - 'Marathon', - 'Events' - ]), - sizedBoxHeight(35.h), - ListView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: 2, - itemBuilder: (context, index) { - return Container( - padding: const EdgeInsets.symmetric( - vertical: 12, horizontal: 16), - child: CommentTreeWidget( - Comment( - avatar: 'assets/images/png/Ellipse 52.png', - userName: 'Krishna', - content: - 'felangel made felangel/cubit_and_beyond public'), - [ - Comment( - avatar: 'assets/images/png/Ellipse 52.png', - userName: 'Kishan', - content: 'Sample comment from kishan'), - Comment( - avatar: 'assets/images/png/Ellipse 52.png', - userName: 'Ram', - content: - 'A Dart template generator which helps teams generator which helps teams generator which helps teams'), - // Comment( - // avatar: 'null', - // userName: 'null', - // content: - // 'A Dart template generator which helps teams'), - // Comment( - // avatar: 'null', - // userName: 'null', - // content: - // 'A Dart template generator which helps teams generator which helps teams '), - ], - treeThemeData: const TreeThemeData( - lineColor: Color(0xFFD90B2E), lineWidth: 2.5), - avatarRoot: (context, data) => const PreferredSize( - preferredSize: Size.fromRadius(18), - child: CircleAvatar( - radius: 18, - backgroundColor: Colors.grey, - backgroundImage: AssetImage( - 'assets/images/png/Ellipse 52.png', - ), - ), - ), - avatarChild: (context, data) => const PreferredSize( - preferredSize: Size.fromRadius(12), - child: CircleAvatar( - radius: 12, - backgroundColor: Colors.grey, - backgroundImage: AssetImage( - 'assets/images/png/Ellipse 52.png', - ), - ), - ), - contentChild: (context, data) { - print("printing"); - return data.userName! == "Ram" && _hideReplies[index] - ? GestureDetector( - onTap: () { - setState(() { - _hideReplies[index] = false; - }); - }, - child: Container( - child: const Text( - "View more", - style: TextStyle(color: Colors.white), - ), + body: FutureBuilder( + future: futureGroup.future, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center( + child: CircularProgressIndicator( + color: Colors.blue, + ), + ); + } else if (snapshot.hasError) { + return Center( + child: Text( + '${snapshot.error} occurred', + style: TextStyle(fontSize: 18.spMin), + ), + ); + } else if (snapshot.connectionState == ConnectionState.done) { + _setViewMoreList(); + return _buildBody(isKeyboardVisible); + } else { + return const Center(child: Text('Something went wrong')); + } + }, + )); + }); + } + + _buildBody(isKeyboardVisible) { + return Stack(children: [ + Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/png/Ellipse 1496.png"), + fit: BoxFit.fill)), + ), + SingleChildScrollView( + child: + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + postCards( + profileImg: 'assets/images/png/Ellipse 52.png', + title: 'Ryan Dorwat', + mainImg: 'assets/images/png/Rectangle 25.png', + containerTitle: [ + 'Football', + 'Marathon', + 'Events', + 'Marathon', + 'Events' + ]), + sizedBoxHeight(35.h), + + // ListView.builder( + // physics: const NeverScrollableScrollPhysics(), + // shrinkWrap: true, + // itemCount: nestedComments!.data.length, + // itemBuilder: (context, index) { + // List _repliedCommentsSorted = _setComments(index); + + // return Container( + // padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), + // child: CommentTreeWidget( + // Comment( + // avatar: + // nestedComments!.data[index].userDetail!.profilePhoto, + // userName: nestedComments!.data[index].userDetail!.userName, + // content: nestedComments!.data[index].comment), + // [], + // // _repliedCommentsSorted.isNotEmpty ? _repliedCommentsSorted : [], + // treeThemeData: const TreeThemeData( + // lineColor: Color(0xFFD90B2E), lineWidth: 2.5), + // avatarRoot: (context, data) => PreferredSize( + // preferredSize: const Size.fromRadius(18), + // child: CircleAvatar( + // radius: 18, + // backgroundColor: Colors.grey, + // backgroundImage: NetworkImage( + // data.avatar ?? + // "https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png?20150327203541", + // ), + // ), + // ), + // avatarChild: (context, data) => PreferredSize( + // preferredSize: const Size.fromRadius(12), + // child: CircleAvatar( + // radius: 12, + // backgroundColor: Colors.grey, + // backgroundImage: NetworkImage( + // data.avatar ?? + // "https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png?20150327203541", + // ), + // ), + // ), + // contentChild: (context, data) { + // return data.userName! == "Ram" && _hideReplies[index] + // ? GestureDetector( + // onTap: () { + // setState(() { + // _hideReplies[index] = false; + // }); + // }, + // child: Container( + // child: const Text( + // "View more", + // style: TextStyle(color: Colors.white), + // ), + // ), + // ) + // : Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Container( + // padding: const EdgeInsets.symmetric( + // vertical: 8, horizontal: 8), + // decoration: BoxDecoration( + // color: Colors.grey[100], + // borderRadius: BorderRadius.circular(12)), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // '${data.userName}', + // style: Theme.of(context) + // .textTheme + // .bodySmall + // ?.copyWith( + // fontWeight: FontWeight.w600, + // color: Colors.black), + // ), + // const SizedBox( + // height: 4, + // ), + // Text( + // '${data.content}', + // style: Theme.of(context) + // .textTheme + // .bodySmall + // ?.copyWith( + // fontWeight: FontWeight.w300, + // color: Colors.black), + // ), + // ], + // ), + // ), + // DefaultTextStyle( + // style: Theme.of(context) + // .textTheme + // .bodySmall! + // .copyWith( + // color: Colors.grey[700], + // fontWeight: FontWeight.bold), + // child: const Padding( + // padding: EdgeInsets.only(top: 4), + // child: Row( + // children: [ + // SizedBox( + // width: 8, + // ), + // Text('Like'), + // SizedBox( + // width: 24, + // ), + // Text('Reply'), + // ], + // ), + // ), + // ) + // ], + // ); + // }, + // contentRoot: (context, data) { + // return Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Container( + // padding: const EdgeInsets.symmetric( + // vertical: 8, horizontal: 8), + // decoration: BoxDecoration( + // color: Colors.grey[100], + // borderRadius: BorderRadius.circular(12)), + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Text( + // 'dangngocduc', + // style: Theme.of(context) + // .textTheme + // .bodySmall! + // .copyWith( + // fontWeight: FontWeight.w600, + // color: Colors.black), + // ), + // const SizedBox( + // height: 4, + // ), + // Text( + // '${data.content}', + // style: Theme.of(context) + // .textTheme + // .bodySmall! + // .copyWith( + // fontWeight: FontWeight.w300, + // color: Colors.black), + // ), + // ], + // ), + // ), + // DefaultTextStyle( + // style: Theme.of(context).textTheme.bodySmall!.copyWith( + // color: Colors.grey[700], + // fontWeight: FontWeight.bold), + // child: const Padding( + // padding: EdgeInsets.only(top: 4), + // child: Row( + // children: [ + // SizedBox( + // width: 8, + // ), + // Text('Like'), + // SizedBox( + // width: 24, + // ), + // Text('Reply'), + // ], + // ), + // ), + // ) + // ], + // ); + // }, + // ), + // ); + // }, + // ), + + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: nestedComments?.data.length, + itemBuilder: (context, index) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 16.w), + child: Column( + children: [ + GestureDetector( + onLongPressStart: (details) { + nestedComments?.data[index].userDetail!.id + .toString() != + userIdGlobal + ? null + : showMenu( + context: context, + position: RelativeRect.fromLTRB( + details.globalPosition.dx, + details.globalPosition.dy, + details.globalPosition.dx + 1, + details.globalPosition.dy + 1, ), - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 8), - decoration: BoxDecoration( - color: Colors.grey[100], - borderRadius: - BorderRadius.circular(12)), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - '${data.userName}', - style: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith( - fontWeight: FontWeight.w600, - color: Colors.black), - ), - const SizedBox( - height: 4, - ), - Text( - '${data.content}', - style: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith( - fontWeight: FontWeight.w300, - color: Colors.black), - ), - ], - ), + items: [ + const PopupMenuItem( + value: 0, + child: Text("Delete"), ), - DefaultTextStyle( - style: Theme.of(context) - .textTheme - .bodySmall! - .copyWith( - color: Colors.grey[700], - fontWeight: FontWeight.bold), - child: const Padding( - padding: EdgeInsets.only(top: 4), - child: Row( - children: [ - SizedBox( - width: 8, - ), - Text('Like'), - SizedBox( - width: 24, - ), - Text('Reply'), - ], - ), - ), - ) ], - ); + elevation: 8.0, + ).then((value) { + if (value == 0) { + _deleteComment(nestedComments! + .data[index].id + .toString()); + } + }); }, - contentRoot: (context, data) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: const EdgeInsets.symmetric( - vertical: 8, horizontal: 8), - decoration: BoxDecoration( - color: Colors.grey[100], - borderRadius: BorderRadius.circular(12)), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'dangngocduc', - style: Theme.of(context) - .textTheme - .bodySmall! - .copyWith( - fontWeight: FontWeight.w600, - color: Colors.black), - ), - const SizedBox( - height: 4, - ), - Text( - '${data.content}', - style: Theme.of(context) - .textTheme - .bodySmall! - .copyWith( - fontWeight: FontWeight.w300, - color: Colors.black), - ), - ], - ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CircleAvatar( + radius: 20.r, + foregroundImage: NetworkImage( + nestedComments! + .data[index].userDetail!.profilePhoto ?? + "https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png?20150327203541", ), - DefaultTextStyle( - style: Theme.of(context) - .textTheme - .bodySmall! - .copyWith( - color: Colors.grey[700], - fontWeight: FontWeight.bold), - child: const Padding( - padding: EdgeInsets.only(top: 4), - child: Row( - children: [ - SizedBox( - width: 8, - ), - Text('Like'), - SizedBox( - width: 24, - ), - Text('Reply'), - ], + ), + sizedBoxWidth(15.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + text12w400_FCFCFC_blur(nestedComments! + .data[index].userDetail!.userName ?? + ""), + text14w400_FCFCFC( + nestedComments!.data[index].comment ?? + ""), + SizedBox(height: 10.h), + GestureDetector( + onTap: () { + _focusTextField(); + _controllerComments.text = + "@${nestedComments!.data[index].userDetail!.userName!}"; + setState(() { + repliedCommentId = nestedComments! + .data[index].id + .toString(); + }); + }, + child: text10w400_FCFCFC_blur("Reply")), + SizedBox(height: 20.h), + nestedComments! + .data[index].repliedComment.isEmpty + ? const SizedBox() + : hideReplies[index] + ? GestureDetector( + onTap: () { + _toggleReplies(index); + }, + child: text10w400_FCFCFC_blur( + "Hide replies"), + ) + : GestureDetector( + onTap: () { + _toggleReplies(index); + }, + child: text10w400_FCFCFC_blur( + "View ${nestedComments!.data[index].repliedComment.length} more replies"), + ), + SizedBox(height: 10.h), + !hideReplies[index] + ? const SizedBox() + : ListView.builder( + physics: + const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: nestedComments!.data[index] + .repliedComment.length, + itemBuilder: (context, index2) { + return GestureDetector( + onLongPressStart: + (LongPressStartDetails + details) { + nestedComments + ?.data[index] + .repliedComment[ + index2] + .userDetail + ?.id + .toString() != + userIdGlobal + ? null + : showMenu( + context: context, + position: RelativeRect + .fromLTRB( + details.globalPosition + .dx, + details.globalPosition + .dy, + details.globalPosition + .dx + + 1, + details.globalPosition + .dy + + 1, + ), + items: [ + const PopupMenuItem< + int>( + value: 0, + child: + Text("Delete"), + ), + ], + elevation: 8.0, + ).then((value) { + if (value == 0) { + _deleteRepliedComment( + nestedComments! + .data[index] + .repliedComment[ + index2] + .id + .toString()); + } + }); + }, + child: ListTile( + leading: Column( + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + CircleAvatar( + radius: 13.r, + foregroundImage: + NetworkImage( + nestedComments! + .data[index] + .repliedComment[ + index2] + .userDetail + ?.profilePhoto ?? + "https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png?20150327203541", + ), + ), + ], + ), + title: text12w400_FCFCFC_blur( + nestedComments! + .data[index] + .repliedComment[ + index2] + .userDetail + ?.userName ?? + ""), + subtitle: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + text14w400_FCFCFC( + nestedComments! + .data[index] + .repliedComment[ + index2] + .comment ?? + ""), + SizedBox(height: 10.h), + GestureDetector( + onTap: () { + _focusTextField(); + _controllerComments + .text = + "@${nestedComments!.data[index].repliedComment[index2].userDetail!.userName!}"; + setState(() { + repliedCommentId = + nestedComments! + .data[index] + .repliedComment[ + index2] + .postsMasterCommentXid + .toString(); + }); + }, + child: + text10w400_FCFCFC_blur( + "Reply")), + ], + ), + ), + ); + }) + ], + ), + ), + ], + ), + ), + sizedBoxHeight(20.h), + //sizedBoxHeight(85.h) + ], + )); + }), + sizedBoxHeight(25.h), + ])), + Positioned.fill( + top: 625.h - MediaQuery.of(context).viewInsets.bottom, + // isKeyboardVisible ? 270.h : 625.h, + right: 16.0, + left: 16.0, + child: Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.only(top: 15, bottom: 15), + child: Row( + children: [ + Obx(() { + return Expanded( + child: CustomTextFormField( + textEditingController: _controllerComments, + focusNode: _focusNode, + hintText: "Add comment", + suffixIcon: GestureDetector( + onTap: () { + if (_controllerComments.text.isEmpty) { + print("Enter some text"); + } else { + _commentsHelper.isLoading.value = true; + if (repliedCommentId != "") { + _postRepliesOnComment(repliedCommentId); + } else { + _postComments(); + } + } + }, + child: _commentsHelper.isLoading.value + ? Container( + padding: const EdgeInsets.all(10), + height: 10.h, + width: 10.w, + child: const CircularProgressIndicator()) + : SizedBox( + height: 20.h, + width: 25.w, + child: Center( + child: Image.asset( + "assets/images/png/iconoir_send.png", + height: 20.h, + width: 25.w, + ), ), ), - ) - ], - ); - }, + ), ), ); - }, - ), - - // Padding( - // padding: EdgeInsets.symmetric(horizontal: 16.w), - // child: Column(children: [ - // Row( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // CircleAvatar( - // radius: 20.r, - // foregroundImage: const AssetImage( - // "assets/images/png/Ellipse 48.png", - // ), - // ), - // sizedBoxWidth(15.w), - // Expanded( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // text12w400_FCFCFC_blur("Roger Saris"), - // text14w400_FCFCFC( - // "Lorem Ipsum has been the industry's standard dummy text 😍"), - // text10w400_FCFCFC_blur("Reply. . . ") - // ], - // ), - // ), - // ], - // ), - // sizedBoxHeight(50.h), - // Align( - // alignment: Alignment.bottomCenter, - // child: Padding( - // padding: const EdgeInsets.only(top: 15, bottom: 15), - // child: Row( - // children: [ - // Expanded( - // child: CustomTextFormField( - // hintText: "Add comment", - // suffixIcon: SizedBox( - // height: 20.h, - // width: 25.w, - // child: Center( - // child: Image.asset( - // "assets/images/png/iconoir_send.png", - // height: 20.h, - // width: 25.w, - // ), - // ), - // ), - // ), - // ) - // ], - // ), - // )), - // sizedBoxHeight(85.h) - // ])) - ])) - ])); + }) + ], + ), + )), + ), + ]); } Widget postCards({ @@ -336,7 +676,7 @@ class _PostDetailsScreenState extends State { return commonGlassUI( width: double.infinity, - height: 570.h, + height: 800.h, borderwidth: 0, borderRadius: BorderRadius.circular(0), customWidget: Column( @@ -467,7 +807,7 @@ class _PostDetailsScreenState extends State { ), ], ), - sizedBoxHeight(5.h), + sizedBoxHeight(15.h), Row( children: [ Image.asset( @@ -499,7 +839,7 @@ class _PostDetailsScreenState extends State { // Get.toNamed(RouteName.postdetailsScreen); }, child: SizedBox( - height: 163.h, + height: 390.h, width: double.infinity, child: Image.asset( mainImg, @@ -691,7 +1031,4 @@ class _PostDetailsScreenState extends State { ], ); } - } - - diff --git a/lib/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsHelper.dart b/lib/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsHelper.dart new file mode 100644 index 0000000..3456efe --- /dev/null +++ b/lib/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsHelper.dart @@ -0,0 +1,5 @@ +import 'package:get/get.dart'; + +class CommentsHelper extends GetxController { + RxBool isLoading = false.obs; +} diff --git a/lib/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsRepository.dart b/lib/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsRepository.dart new file mode 100644 index 0000000..f4f741b --- /dev/null +++ b/lib/Main_Screens/Community_HomePage/PostDetailScreen/ViewModel/CommentsRepository.dart @@ -0,0 +1,51 @@ +import 'package:regroup/Common/api_urls.dart'; +import 'package:regroup/Common/base_manager.dart'; +import 'package:regroup/Common/controller/data/network/network_api.dart'; +import 'package:regroup/Main_Screens/Community_HomePage/PostDetailScreen/Model/LikePostModel.dart'; +import 'package:regroup/Main_Screens/Community_HomePage/PostDetailScreen/Model/NestedCommentsModel.dart'; + +NestedCommentsModel? nestedComments; + +class CommentsRepository { + Future> getAllComments() async { + final response = await NetworkApiServices().getApi( + "${ApiUrls.getComments}?manage_posts_xid=1", + ); + if (response.status == ResponseStatus.SUCCESS) { + nestedComments = NestedCommentsModel.fromJson(response.data); + } + return response; + } + + Future> postComments(updata) async { + final response = await NetworkApiServices().postApi( + updata, + ApiUrls.storeComments, + ); + return response; + } + + Future> postRepliesOnComments(updata) async { + final response = await NetworkApiServices().postApi( + updata, + ApiUrls.storeRepliesOnComments, + ); + return response; + } + + Future> deleteComments(updata) async { + final response = await NetworkApiServices().postApi( + updata, + ApiUrls.deleteComments, + ); + return response; + } + + Future> deleteRepliedComments(updata) async { + final response = await NetworkApiServices().postApi( + updata, + ApiUrls.deleteRepliesComments, + ); + return response; + } +} diff --git a/lib/Utils/Common/CustomTextformfield.dart b/lib/Utils/Common/CustomTextformfield.dart index ea846a7..ad76c16 100644 --- a/lib/Utils/Common/CustomTextformfield.dart +++ b/lib/Utils/Common/CustomTextformfield.dart @@ -31,7 +31,7 @@ class CustomTextFormField extends StatefulWidget { this.onTap, this.suffixIcon, this.opacity1 = 0.04, - this.opacity2 = 0.05, + this.opacity2 = 0.05, this.focusNode, }) : super(key: key); dynamic validator; @@ -52,7 +52,7 @@ class CustomTextFormField extends StatefulWidget { final Widget? suffixIcon; final double opacity1; final double opacity2; - + final FocusNode? focusNode; String? validationMessage; @override @@ -99,6 +99,7 @@ class _CustomTextFormFieldState extends State { borderRadius: BorderRadius.circular(30.r), border: Border.all(color: const Color(0xff434A53), width: 0.8), child: TextFormField( + focusNode: widget.focusNode, style: TextStyle( fontSize: 16.sp, color: Colors.white, fontFamily: 'Helvetica'), cursorColor: Colors.red, @@ -153,9 +154,7 @@ class _CustomTextFormFieldState extends State { ], ), ) - : widget.suffixIcon == null - ? null - : widget.suffixIcon!, + : widget.suffixIcon, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(horizontal: 20.h, vertical: 13.w), @@ -237,8 +236,8 @@ class _CustomTextFormField2State extends State { void validateField(String value) { setState(() { - widget.validationMessage = widget.validator?.call(value) ?? - (value.isEmpty ? "" : null); + widget.validationMessage = + widget.validator?.call(value) ?? (value.isEmpty ? "" : null); }); } diff --git a/lib/main.dart b/lib/main.dart index 0498ee0..171c6cc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -115,6 +115,7 @@ class _MyAppState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { return ScreenUtilInit( + //useInheritedMediaQuery: true, builder: (BuildContext context, Widget? child) => GetMaterialApp( title: 'Regroup', theme: ThemeData( @@ -124,14 +125,11 @@ class _MyAppState extends State with WidgetsBindingObserver { debugShowCheckedModeBanner: false, // initialRoute: RouteName.individualactivitystep2, - - initialRoute: RouteName.splashScreen, - getPages: AppRoutes.appRoutes(), ), designSize: const Size(390, 844), ); - } + } } diff --git a/lib/onboarding/Signup/view_model/getUserprofile.dart b/lib/onboarding/Signup/view_model/getUserprofile.dart index e663759..344240b 100644 --- a/lib/onboarding/Signup/view_model/getUserprofile.dart +++ b/lib/onboarding/Signup/view_model/getUserprofile.dart @@ -36,11 +36,16 @@ class Getuserdetails { 'phone', getuserobj?.data?.userData?.phoneNumber ?? ""); await prefs.setString('accountTypefromLogin', getuserobj?.data?.userData?.principalTypeXid.toString() ?? ""); + await prefs.setString( + 'userId', getuserobj?.data?.userData?.id.toString() ?? ""); + emailid = prefs.getString('email'); myusername = prefs.getString('username'); fullname = prefs.getString('fullname'); phonenumber = prefs.getString('phone'); globalAccountType = prefs.getString('accountTypefromLogin'); + userIdGlobal = prefs.getString('userId') ?? "0"; + globalAccountType = getuserobj?.data?.userData?.principalTypeXid.toString(); } else if (responseData is String) { diff --git a/pubspec.lock b/pubspec.lock index 35f959c..de4afa4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -350,6 +350,54 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0-beta.2" + flutter_keyboard_visibility: + dependency: "direct main" + description: + name: flutter_keyboard_visibility + sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_keyboard_visibility_linux: + dependency: transitive + description: + name: flutter_keyboard_visibility_linux + sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_macos: + dependency: transitive + description: + name: flutter_keyboard_visibility_macos + sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_platform_interface: + dependency: transitive + description: + name: flutter_keyboard_visibility_platform_interface + sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_web: + dependency: transitive + description: + name: flutter_keyboard_visibility_web + sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_keyboard_visibility_windows: + dependency: transitive + description: + name: flutter_keyboard_visibility_windows + sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 + url: "https://pub.dev" + source: hosted + version: "1.0.0" flutter_launcher_icons: dependency: "direct dev" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2f9ba08..2e748e3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -77,6 +77,7 @@ dependencies: timer_button: ^2.1.1 flutter_html: ^3.0.0-beta.2 comment_tree: ^0.3.0 + flutter_keyboard_visibility: ^6.0.0