From 692e157c4c4bd70b86db72fe320f48d67f364029 Mon Sep 17 00:00:00 2001 From: Anuj Kumar <144224503+AnujLM@users.noreply.github.com> Date: Wed, 10 Jan 2024 12:26:03 +0530 Subject: [PATCH 1/5] feat(Activity): added user activity feature --- example/lib/cred_screen.dart | 8 +- example/lib/screens/activity_screen.dart | 37 ++ example/lib/screens/root_screen.dart | 94 ++++ lib/assets/icons/mistery-box.svg | 10 + lib/likeminds_feed_ss_fl.dart | 1 + lib/src/utils/constants/assets_constants.dart | 2 + lib/src/views/activity/activity_feed.dart | 477 ++++++++++++++++++ lib/src/views/media_preview.dart | 50 +- lib/src/widgets/activity/activity_tile.dart | 48 ++ lib/src/widgets/activity/activity_widget.dart | 316 ++++++++++++ lib/src/widgets/post/post_widget.dart | 48 +- lib/src/widgets/widgets.dart | 2 + pubspec.yaml | 5 +- 13 files changed, 1054 insertions(+), 44 deletions(-) create mode 100644 example/lib/screens/activity_screen.dart create mode 100644 example/lib/screens/root_screen.dart create mode 100644 lib/assets/icons/mistery-box.svg create mode 100644 lib/src/views/activity/activity_feed.dart create mode 100644 lib/src/widgets/activity/activity_tile.dart create mode 100644 lib/src/widgets/activity/activity_widget.dart create mode 100644 lib/src/widgets/widgets.dart diff --git a/example/lib/cred_screen.dart b/example/lib/cred_screen.dart index d981188..e9c08d2 100644 --- a/example/lib/cred_screen.dart +++ b/example/lib/cred_screen.dart @@ -8,6 +8,7 @@ import 'package:likeminds_feed_ss_sample/bloc_observer/routing_bloc_listener.dar import 'package:likeminds_feed_ss_sample/likeminds_callback.dart'; import 'package:likeminds_feed_ss_sample/main.dart'; import 'package:likeminds_feed_ss_sample/network_handling.dart'; +import 'package:likeminds_feed_ss_sample/screens/root_screen.dart'; import 'package:overlay_support/overlay_support.dart'; import 'package:uni_links/uni_links.dart'; @@ -283,8 +284,13 @@ class _CredScreenState extends State { // } MaterialPageRoute route = MaterialPageRoute( // INIT - Get the LMFeed instance and pass the credentials (if any) - builder: (context) => lmFeed!, + builder: (context) => TabApp( + feedWidget: lmFeed!, + uuid: _userIdController.text, + ), ); + debugPrint( + "---------------${lmFeed!.userId!}-------------------"); Navigator.of(context).pushReplacement(route); }, child: Container( diff --git a/example/lib/screens/activity_screen.dart b/example/lib/screens/activity_screen.dart new file mode 100644 index 0000000..c27ea67 --- /dev/null +++ b/example/lib/screens/activity_screen.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:likeminds_feed_ss_fl/likeminds_feed_ss_fl.dart'; +import 'package:likeminds_feed_ss_sample/credentials/credentials.dart'; + +class ActivityScreen extends StatefulWidget { + const ActivityScreen({super.key, required this.uuid}); + final String uuid; + + @override + State createState() => _ActivityScreenState(); +} + +class _ActivityScreenState extends State { + late String userId; + @override + void initState() { + const isProd = prodFlag; + userId = widget.uuid.isEmpty + ? isProd + ? CredsProd.botId + : CredsDev.botId + : widget.uuid; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + // backgroundColor: ColorTheme.backgroundColor, + appBar: AppBar( + title: const Text('My Activity'), + // backgroundColor: ColorTheme.backgroundColor, + ), + body: SSActivityWidget(uuid: userId), + ); + } +} diff --git a/example/lib/screens/root_screen.dart b/example/lib/screens/root_screen.dart new file mode 100644 index 0000000..79a775c --- /dev/null +++ b/example/lib/screens/root_screen.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:likeminds_feed_ss_sample/screens/activity_screen.dart'; + +class TabApp extends StatefulWidget { + final Widget feedWidget; + final String uuid; + const TabApp({ + super.key, + required this.feedWidget, + required this.uuid, + }); + + @override + State createState() => _TabAppState(); +} + +class _TabAppState extends State with TickerProviderStateMixin { + late TabController tabController; + + @override + void initState() { + // TODO: implement initState + super.initState(); + tabController = TabController(length: 2, vsync: this); + tabController.addListener(() { + setState(() {}); + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + bottomNavigationBar: NavigationBar( + selectedIndex: tabController.index, + onDestinationSelected: (index) { + tabController.animateTo(index); + setState(() {}); + }, + elevation: 10, + indicatorColor: Color(0xFF3B82F6), + backgroundColor: Color(0xFF3B82F6).withOpacity(0.1), + destinations: const [ + NavigationDestination( + icon: Icon( + Icons.home, + ), + selectedIcon: Icon( + Icons.home, + color: Colors.white, + ), + label: 'Home', + ), + NavigationDestination( + icon: Icon( + Icons.person_2_sharp, + ), + selectedIcon: Icon( + Icons.person_2_sharp, + color: Colors.white, + ), + label: 'Activity', + ), + ], + ), + body: TabBarView( + controller: tabController, + children: [ + HomeScreen( + feedWidget: widget.feedWidget, + ), // First tab content + ActivityScreen( + uuid: widget.uuid, + ), // Second tab content + ], + ), + ), + ); + } +} + +class HomeScreen extends StatelessWidget { + final Widget feedWidget; + + const HomeScreen({ + super.key, + required this.feedWidget, + }); + + @override + Widget build(BuildContext context) { + return feedWidget; + } +} diff --git a/lib/assets/icons/mistery-box.svg b/lib/assets/icons/mistery-box.svg new file mode 100644 index 0000000..e190819 --- /dev/null +++ b/lib/assets/icons/mistery-box.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lib/likeminds_feed_ss_fl.dart b/lib/likeminds_feed_ss_fl.dart index a589158..dc7f60e 100644 --- a/lib/likeminds_feed_ss_fl.dart +++ b/lib/likeminds_feed_ss_fl.dart @@ -22,6 +22,7 @@ export 'src/utils/share/share_post.dart'; export 'src/utils/local_preference/user_local_preference.dart'; export 'src/blocs/bloc.dart'; export 'src/utils/deep_link/deep_link_handler.dart'; +export 'src/widgets/widgets.dart'; /// Flutter environment manager v0.0.1 const prodFlag = !bool.fromEnvironment('DEBUG'); diff --git a/lib/src/utils/constants/assets_constants.dart b/lib/src/utils/constants/assets_constants.dart index 896129e..3609e2e 100644 --- a/lib/src/utils/constants/assets_constants.dart +++ b/lib/src/utils/constants/assets_constants.dart @@ -20,6 +20,8 @@ const String kAssetPDFIcon = "packages/likeminds_feed_ss_fl/assets/icons/pdf.svg"; const String kAssetChatIcon = "packages/likeminds_feed_ss_fl/assets/icons/chat_lines.svg"; +const String kAssetNoPostsIcon = + "packages/likeminds_feed_ss_fl/assets/icons/mistery-box.svg"; const List svgAssets = [ kAssetDocPDFIcon, diff --git a/lib/src/views/activity/activity_feed.dart b/lib/src/views/activity/activity_feed.dart new file mode 100644 index 0000000..8f20b57 --- /dev/null +++ b/lib/src/views/activity/activity_feed.dart @@ -0,0 +1,477 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:likeminds_feed_ss_fl/likeminds_feed_ss_fl.dart'; +import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; +import 'package:likeminds_feed/likeminds_feed.dart'; +import 'package:likeminds_feed_ss_fl/src/blocs/comment/add_comment_reply/add_comment_reply_bloc.dart'; +import 'package:likeminds_feed_ss_fl/src/blocs/comment/toggle_like_comment/toggle_like_comment_bloc.dart'; +import 'package:likeminds_feed_ss_fl/src/utils/constants/assets_constants.dart'; +import 'package:likeminds_feed_ss_fl/src/utils/constants/ui_constants.dart'; +import 'package:likeminds_feed_ss_fl/src/utils/post/post_action_id.dart'; +import 'package:likeminds_feed_ss_fl/src/views/post_detail_screen.dart'; +import 'package:likeminds_feed_ss_fl/src/widgets/delete_dialog.dart'; +import 'package:likeminds_feed_ss_fl/src/widgets/post/post_widget.dart'; +import 'package:likeminds_feed_ui_fl/likeminds_feed_ui_fl.dart'; +import 'package:timeago/timeago.dart' as timeago; + +class SSActivityFeedScreen extends StatefulWidget { + const SSActivityFeedScreen({super.key, required this.uuid}); + final String uuid; + + @override + State createState() => _SSActivityFeedScreenState(); +} + +class _SSActivityFeedScreenState extends State { + final PagingController _pagingController = + PagingController(firstPageKey: 1); + + GetUserActivityResponse? _userActivityResponse; + + late final AddCommentReplyBloc _addCommentReplyBloc; + late final ToggleLikeCommentBloc _toggleLikeCommentBloc; + + @override + void initState() { + _addCommentReplyBloc = AddCommentReplyBloc(); + _toggleLikeCommentBloc = ToggleLikeCommentBloc(); + _pagingController.addPageRequestListener((pageKey) { + _fetchPage(pageKey); + // _pagingController.appendLastPage([]); + }); + super.initState(); + } + + void _fetchPage(int pageKey) async { + try { + final request = (GetUserActivityRequestBuilder() + ..uuid(widget.uuid) + ..page(pageKey) + ..pageSize(10)) + .build(); + _userActivityResponse = + await locator().getUserActivity(request); + final isLastPage = _userActivityResponse!.activities!.length < 10; + if (isLastPage) { + _pagingController.appendLastPage(_userActivityResponse!.activities!); + } else { + final nextPageKey = pageKey + 1; + _pagingController.appendPage( + _userActivityResponse!.activities!, nextPageKey); + } + } catch (error) { + _pagingController.error = error; + } + } + + String getUserName(String actionBy) { + if (widget.uuid == + _userActivityResponse!.users![actionBy]!.sdkClientInfo!.userUniqueId) { + return 'You'; + } else { + return _userActivityResponse!.users![actionBy]!.name; + } + } + + String getActivityTextWithoutName(String activityText, String actionBy) { + final String name = getUserName(actionBy); + return activityText.replaceFirst(name, ''); + } + + @override + void dispose() { + _addCommentReplyBloc.close(); + _toggleLikeCommentBloc.close(); + _pagingController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Theme( + data: LMThemeData.suraasaTheme, + child: Scaffold( + backgroundColor: const Color(0xFFF8FAFC), + appBar: AppBar( + leading: LMTextButton( + text: const LMTextView( + text: 'Back', + textStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: LMThemeData.kPrimaryColor, + ), + ), + icon: const LMIcon( + type: LMIconType.icon, + icon: Icons.arrow_back_ios, + size: 16, + color: LMThemeData.kPrimaryColor), + margin: 2, + padding: const EdgeInsets.only(left: 4), + onTap: () { + Navigator.pop(context); + }, + ), + centerTitle: true, + title: const LMTextView( + text: 'Activity', + textStyle: TextStyle( + fontSize: 17, + fontWeight: FontWeight.w500, + ), + ), + ), + body: MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => _addCommentReplyBloc, + ), + BlocProvider( + create: (context) => _toggleLikeCommentBloc, + ), + ], + child: PagedListView( + pagingController: _pagingController, + builderDelegate: PagedChildBuilderDelegate( + noItemsFoundIndicatorBuilder: (context) { + return const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LMIcon( + type: LMIconType.svg, + assetPath: kAssetNoPostsIcon, + size: 130, + ), + LMTextView( + text: 'No Posts to show', + textStyle: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w700, + ), + ), + SizedBox(height: 20), + ], + ), + ); + }, itemBuilder: (context, item, index) { + //todo: change this + final PostViewData post = item.action == 7 + ? PostViewData.fromPost( + post: item.activityEntityData.postData!) + : (PostViewDataBuilder() + ..id(item.activityEntityData.id) + ..isEdited(item.activityEntityData.isEdited!) + ..text(item.activityEntityData.text) + ..attachments(item.activityEntityData.attachments!) + ..communityId(item.activityEntityData.communityId) + ..isPinned(item.activityEntityData.isPinned!) + ..topics(item.activityEntityData.topics!) + ..userId(item.activityEntityData.userId!) + ..likeCount(item.activityEntityData.likesCount!) + ..commentCount(item.activityEntityData.commentsCount!) + ..isSaved(item.activityEntityData.isSaved!) + ..isLiked(item.activityEntityData.isLiked!) + ..menuItems(item.activityEntityData.menuItems!) + ..createdAt(DateTime.fromMillisecondsSinceEpoch( + item.activityEntityData.createdAt)) + ..updatedAt(DateTime.fromMillisecondsSinceEpoch( + item.activityEntityData.updatedAt!))) + .build(); + + final user = _userActivityResponse! + .users![item.activityEntityData.userId]!; + return Column( + children: [ + Column( + children: [ + const SizedBox(height: 8), + SSPostWidget( + post: post, + user: user, + activityHeader: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + text: + '${getUserName(_userActivityResponse!.activities!.elementAt(index).actionBy.first)}', + style: const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + color: LMThemeData.kGrey1Color, + ), + children: [ + TextSpan( + text: + '${getActivityTextWithoutName(_userActivityResponse!.activities!.elementAt(index).activityText, _userActivityResponse!.activities!.elementAt(index).actionBy.first)}', + style: const TextStyle( + fontWeight: FontWeight.w400, + fontSize: 14, + color: LMThemeData.kGrey1Color, + ), + ), + ], + ), + ), + LMThemeData.kVerticalPaddingMedium, + const Divider( + color: LMThemeData.onSurface, + thickness: 1, + ), + ], + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PostDetailScreen( + postId: post.id, + ), + ), + ); + }, + topics: _userActivityResponse!.topics!, + refresh: (val) {}, + isFeed: true, + ), + ], + ), + if (item.action == 7) + Container( + padding: const EdgeInsets.symmetric(horizontal: 18), + decoration: const BoxDecoration( + color: LMThemeData.kWhiteColor, + border: Border( + bottom: BorderSide( + width: 0.2, + color: Colors.black45, + ), + ), + ), + child: Column( + children: [ + const Divider( + color: LMThemeData.onSurface, + thickness: 1, + ), + StatefulBuilder(builder: (context, setCommentState) { + final commentData = item.activityEntityData; + commentData.menuItems!.removeWhere((element) => + element.id == commentReportId || + element.id == commentEditId); + return LMCommentTile( + key: ValueKey(item.id), + onTagTap: (String userId) { + locator().routeToProfile(userId); + }, + onMenuTap: (id) { + if (id == commentDeleteId) { + showDialog( + context: context, + builder: (childContext) => + deleteConfirmationDialog( + childContext, + title: 'Delete Comment', + userId: commentData.userId!, + content: + 'Are you sure you want to delete this post. This action can not be reversed.', + action: (String reason) async { + Navigator.of(childContext).pop(); + //Implement delete post analytics tracking + LMAnalytics.get().track( + AnalyticsKeys.commentDeleted, + { + "post_id": commentData.postId, + "comment_id": commentData.id, + }, + ); + locator() + .lmAnalyticsBloc + .add(FireAnalyticEvent( + eventName: AnalyticsKeys + .commentDeleted, + eventProperties: { + "post_id": + commentData.postId, + "comment_id": + commentData.id, + }, + )); + + _addCommentReplyBloc.add(DeleteComment( + (DeleteCommentRequestBuilder() + ..postId( + commentData.postId!) + ..commentId( + commentData.id) + ..reason(reason.isEmpty + ? "Reason for deletion" + : reason)) + .build())); + }, + actionText: 'Delete', + )); + } else if (id == commentEditId) { + _addCommentReplyBloc.add(EditCommentCancel()); + _addCommentReplyBloc.add( + EditingComment( + commentId: commentData.id, + text: commentData.text, + ), + ); + } + }, + comment: Reply( + userId: commentData.userId!, + text: commentData.text, + level: 0, + likesCount: commentData.likesCount!, + repliesCount: commentData.replies!.length, + menuItems: commentData.menuItems!, + createdAt: DateTime.fromMillisecondsSinceEpoch( + commentData.createdAt), + updatedAt: DateTime.fromMillisecondsSinceEpoch( + commentData.updatedAt!), + isLiked: commentData.isLiked!, + id: commentData.id, + ), + user: user, + profilePicture: LMProfilePicture( + backgroundColor: LMThemeData.kPrimaryColor, + fallbackText: user.name, + onTap: () { + if (user.sdkClientInfo != null) { + locator().routeToProfile( + user.sdkClientInfo!.userUniqueId); + } + }, + imageUrl: user.imageUrl, + size: 36, + ), + subtitleText: LMTextView( + text: + "@${user.name.toLowerCase().split(' ').join()} ยท ${timeago.format(DateTime.fromMillisecondsSinceEpoch(commentData.createdAt))}", + textStyle: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + color: LMThemeData.kSecondaryColor700, + ), + ), + actionsPadding: const EdgeInsets.only(left: 48), + commentActions: [ + LMTextButton( + margin: 10, + text: LMTextView( + text: commentData.likesCount == 0 + ? "Like" + : commentData.likesCount == 1 + ? "1 Like" + : "${commentData.likesCount} Likes", + textStyle: const TextStyle( + color: LMThemeData.kSecondaryColor700, + fontSize: 12), + ), + activeText: LMTextView( + text: commentData.likesCount == 0 + ? "Like" + : commentData.likesCount == 1 + ? "1 Like" + : "${commentData.likesCount} Likes", + textStyle: const TextStyle( + color: LMThemeData.kPrimaryColor, + fontSize: 12), + ), + onTap: () { + _toggleLikeCommentBloc.add( + ToggleLikeComment( + toggleLikeCommentRequest: + (ToggleLikeCommentRequestBuilder() + ..commentId(commentData.id) + ..postId(post.id)) + .build(), + ), + ); + setCommentState(() { + if (commentData.isLiked!) { + item.activityEntityData.likesCount = + commentData.likesCount! - 1; + } else { + item.activityEntityData.likesCount = + commentData.likesCount! + 1; + } + item.activityEntityData.isLiked = + !commentData.isLiked!; + }); + }, + icon: const LMIcon( + type: LMIconType.svg, + assetPath: kAssetLikeIcon, + size: 20, + ), + activeIcon: const LMIcon( + type: LMIconType.svg, + assetPath: kAssetLikeFilledIcon, + size: 20, + ), + isActive: commentData.isLiked!, + ), + const SizedBox(width: 12), + Row( + children: [ + LMTextButton( + margin: 10, + text: const LMTextView( + text: "Reply", + textStyle: TextStyle( + fontSize: 12, + )), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + PostDetailScreen( + postId: post.id, + ), + ), + ); + }, + icon: const LMIcon( + type: LMIconType.svg, + assetPath: kAssetCommentIcon, + size: 20, + ), + ), + LMThemeData.kHorizontalPaddingMedium, + commentData.replies!.isNotEmpty + ? LMTextButton( + onTap: () {}, + text: LMTextView( + text: + "${commentData.replies!.length} ${commentData.replies!.length > 1 ? 'Replies' : 'Reply'}", + textStyle: const TextStyle( + color: + LMThemeData.kPrimaryColor, + ), + ), + ) + : const SizedBox() + ], + ), + ], + ); + }), + ], + ), + ), + ], + ); + }), + ), + ), + ), + ); + } +} diff --git a/lib/src/views/media_preview.dart b/lib/src/views/media_preview.dart index a9f9270..0959ff7 100644 --- a/lib/src/views/media_preview.dart +++ b/lib/src/views/media_preview.dart @@ -45,9 +45,15 @@ class _MediaPreviewState extends State { post = widget.post; user = widget.user; position = widget.position; + _filterPostAttachments(); super.initState(); } + _filterPostAttachments() { + postAttachments.removeWhere((element) => + !(element.attachmentType == 1 || element.attachmentType == 2)); + } + @override void dispose() { super.dispose(); @@ -127,27 +133,31 @@ class _MediaPreviewState extends State { videoUrl: postAttachments[index].attachmentMeta.url, showControls: true, ); + } else if (postAttachments[index].attachmentType == 1) { + return Container( + color: Colors.black, + width: MediaQuery.of(context).size.width, + child: Center( + child: ExtendedImage.network( + postAttachments[index].attachmentMeta.url!, + fit: BoxFit.contain, + mode: ExtendedImageMode.gesture, + initGestureConfigHandler: (state) { + return GestureConfig( + hitTestBehavior: HitTestBehavior.opaque, + minScale: 0.9, + animationMinScale: 0.7, + maxScale: 3.0, + animationMaxScale: 3.5, + inPageView: true, + ); + }, + ), + ), + ); + } else { + return const SizedBox.shrink(); } - - return Container( - color: Colors.black, - width: MediaQuery.of(context).size.width, - child: ExtendedImage.network( - postAttachments[index].attachmentMeta.url!, - fit: BoxFit.contain, - mode: ExtendedImageMode.gesture, - initGestureConfigHandler: (state) { - return GestureConfig( - hitTestBehavior: HitTestBehavior.opaque, - minScale: 0.9, - animationMinScale: 0.7, - maxScale: 3.0, - animationMaxScale: 3.5, - inPageView: true, - ); - }, - ), - ); }), ), ValueListenableBuilder( diff --git a/lib/src/widgets/activity/activity_tile.dart b/lib/src/widgets/activity/activity_tile.dart new file mode 100644 index 0000000..55abc46 --- /dev/null +++ b/lib/src/widgets/activity/activity_tile.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +class SSActivityTileWidget extends StatefulWidget { + const SSActivityTileWidget({ + super.key, + this.leading, + this.trailing, + this.title, + this.subtitle, + this.onTap, + this.boxDecoration, + }); + final Widget? leading; + final Widget? trailing; + final Widget? title; + final Widget? subtitle; + final VoidCallback? onTap; + final BoxDecoration? boxDecoration; + + @override + State createState() => _SSActivityTileWidgetState(); +} + +class _SSActivityTileWidgetState extends State { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: widget.onTap, + child: Container( + decoration: widget.boxDecoration, + child: Row( + children: [ + widget.leading ?? const SizedBox.shrink(), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + widget.title ?? const SizedBox.shrink(), + widget.subtitle ?? const SizedBox.shrink(), + ], + ), + ), + widget.trailing ?? const SizedBox.shrink(), + ], + ), + )); + } +} diff --git a/lib/src/widgets/activity/activity_widget.dart b/lib/src/widgets/activity/activity_widget.dart new file mode 100644 index 0000000..4535a4b --- /dev/null +++ b/lib/src/widgets/activity/activity_widget.dart @@ -0,0 +1,316 @@ +import 'package:flutter/material.dart'; +import 'package:likeminds_feed_ss_fl/likeminds_feed_ss_fl.dart'; +import 'package:likeminds_feed_ss_fl/src/utils/constants/ui_constants.dart'; +import 'package:likeminds_feed_ss_fl/src/views/activity/activity_feed.dart'; +import 'package:likeminds_feed_ss_fl/src/views/post_detail_screen.dart'; +import 'package:likeminds_feed_ui_fl/likeminds_feed_ui_fl.dart'; +import 'package:likeminds_feed/likeminds_feed.dart'; +import 'package:likeminds_feed_ui_fl/packages/expandable_text/expandable_text.dart'; +import 'package:timeago/timeago.dart' as timeago; +import 'package:video_player/video_player.dart'; + +class SSActivityWidget extends StatefulWidget { + const SSActivityWidget({super.key, required this.uuid}); + final String uuid; + + @override + State createState() => _SSActivityWidgetState(); +} + +class _SSActivityWidgetState extends State { + GetUserActivityResponse? _activityResponse; + final ValueNotifier _rebuildActivity = ValueNotifier(false); + + @override + void initState() { + loadActivity(); + super.initState(); + } + + void loadActivity() async { + final activityRequest = (GetUserActivityRequestBuilder() + ..uuid(widget.uuid) + ..page(1) + ..pageSize(10)) + .build(); + _activityResponse = await locator().getUserActivity( + activityRequest, + ); + _rebuildActivity.value = !_rebuildActivity.value; + } + + String getUserName(String actionBy) { + if (widget.uuid == + _activityResponse!.users![actionBy]!.sdkClientInfo!.userUniqueId) { + return 'You'; + } else { + return _activityResponse!.users![actionBy]!.name; + } + } + + String getActivityTextWithoutName(String activityText, String actionBy) { + final String name = getUserName(actionBy); + return activityText.replaceFirst(name, ''); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Divider(color: LMThemeData.onSurface), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 8.0), + child: LMTextView( + text: 'Activity', + textStyle: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), + const Divider(color: LMThemeData.onSurface), + ValueListenableBuilder( + valueListenable: _rebuildActivity, + builder: (context, value, child) { + return _activityResponse == null + ? const Center( + child: LMLoader(), + ) + : Column( + children: [ + ListView.builder( + shrinkWrap: true, + itemCount: _activityResponse!.activities!.length <= 3 + ? _activityResponse?.activities?.length + : 3, + itemBuilder: (context, index) { + final activity = + _activityResponse!.activities![index]; + final PostViewData postData = activity.action == 7 + ? PostViewData.fromPost( + post: activity.activityEntityData.postData!) + : (PostViewDataBuilder() + ..id(activity.activityEntityData.id) + ..isEdited( + activity.activityEntityData.isEdited!) + ..text(activity.activityEntityData.text) + ..attachments(activity + .activityEntityData.attachments!) + ..communityId(activity + .activityEntityData.communityId) + ..isPinned( + activity.activityEntityData.isPinned!) + ..topics( + activity.activityEntityData.topics!) + ..userId( + activity.activityEntityData.userId!) + ..likeCount(activity + .activityEntityData.likesCount!) + ..commentCount(activity + .activityEntityData.commentsCount!) + ..isSaved( + activity.activityEntityData.isSaved!) + ..isLiked( + activity.activityEntityData.isLiked!) + ..menuItems(activity + .activityEntityData.menuItems!) + ..createdAt( + DateTime.fromMillisecondsSinceEpoch( + activity.activityEntityData + .createdAt)) + ..updatedAt( + DateTime.fromMillisecondsSinceEpoch( + activity.activityEntityData + .updatedAt!))) + .build(); + late final VideoPlayerController controller; + late final Future futureValue; + if (postData.attachments!.isNotEmpty && + mapIntToMediaType(postData + .attachments![0].attachmentType) == + MediaType.video) { + controller = VideoPlayerController.networkUrl( + Uri.parse(postData + .attachments![0].attachmentMeta.url!)); + futureValue = controller.initialize(); + } + + return Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8.0), + child: Column( + children: [ + SSActivityTileWidget( + title: Row( + children: [ + RichText( + text: TextSpan( + text: + '${getUserName(activity.actionBy.first)}', + style: const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + color: LMThemeData.kGrey1Color, + ), + children: [ + TextSpan( + text: + '${getActivityTextWithoutName(activity.activityText, activity.actionBy.first)}', + style: const TextStyle( + fontWeight: FontWeight.w400, + fontSize: 14, + color: + LMThemeData.kGrey1Color, + ), + ), + ], + ), + ), + const Padding( + padding: EdgeInsets.only(left: 8.0), + child: CircleAvatar( + radius: 3, + backgroundColor: Colors.black, + ), + ), + LMTextView( + text: + ' ${timeago.format(DateTime.fromMillisecondsSinceEpoch(_activityResponse!.activities![index].createdAt))}', + ), + ], + ), + subtitle: Padding( + padding: const EdgeInsets.symmetric( + vertical: 2, + ), + child: ExpandableText(postData.text, + expandText: 'Read More', + maxLines: 2, onTagTap: (tag) { + debugPrint(tag); + }, onLinkTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + PostDetailScreen( + postId: postData.id, + ), + ), + ); + }, + style: const TextStyle( + fontWeight: FontWeight.w400, + fontSize: 14, + )), + ), + trailing: postData + .attachments!.isNotEmpty && + mapIntToMediaType(postData + .attachments![0] + .attachmentType) == + MediaType.image + ? ClipRRect( + borderRadius: + BorderRadius.circular(4), + child: LMImage( + imageUrl: postData.attachments![0] + .attachmentMeta.url, + height: 64, + width: 64, + // borderRadius: 24, + boxFit: BoxFit.cover, + ), + ) + : postData.attachments!.isNotEmpty && + mapIntToMediaType(postData + .attachments![0] + .attachmentType) == + MediaType.video + ? FutureBuilder( + future: futureValue, + builder: (context, snapshot) { + if (snapshot + .connectionState == + ConnectionState.done) { + return ClipRRect( + borderRadius: + BorderRadius.circular( + 4), + child: SizedBox( + height: 64, + width: 64, + child: VideoPlayer( + controller, + ), + ), + ); + } else { + return const SizedBox( + height: 64, + width: 64, + child:LMPostMediaShimmer(),); + } + }, + ) + : const SizedBox.shrink(), + onTap: () { + debugPrint('Activity Tapped'); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + PostDetailScreen( + postId: postData.id, + ), + ), + ); + }, + ), + if (index != + (_activityResponse!.activities!.length <= + 3 + ? (_activityResponse! + .activities!.length - + 1) + : 2)) + const Divider(color: LMThemeData.onSurface), + ], + ), + ); + }, + ), + const Divider(color: LMThemeData.onSurface), + LMTextButton( + text: const LMTextView( + text: 'View More Activity', + textStyle: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 15, + color: LMThemeData.kPrimaryColor), + ), + icon: const LMIcon( + type: LMIconType.icon, + icon: Icons.arrow_forward, + color: LMThemeData.kPrimaryColor, + ), + placement: LMIconPlacement.end, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SSActivityFeedScreen( + uuid: widget.uuid, + ), + ), + ); + }, + ), + ], + ); + }), + const Divider(color: LMThemeData.onSurface) + ], + ); + } +} diff --git a/lib/src/widgets/post/post_widget.dart b/lib/src/widgets/post/post_widget.dart index f42581f..c84e810 100644 --- a/lib/src/widgets/post/post_widget.dart +++ b/lib/src/widgets/post/post_widget.dart @@ -26,6 +26,7 @@ class SSPostWidget extends StatefulWidget { final Function() onTap; final Function()? onCommentButtonTap; final Function(bool isDeleted) refresh; + final Widget? activityHeader; const SSPostWidget({ Key? key, @@ -36,6 +37,7 @@ class SSPostWidget extends StatefulWidget { required this.refresh, required this.isFeed, this.onCommentButtonTap, + this.activityHeader, }) : super(key: key); @override @@ -151,29 +153,31 @@ class _SSPostWidgetState extends State { children: [ ValueListenableBuilder( valueListenable: rebuildPostWidget, - builder: (context, _, __) => isPinned! - ? const Column( - children: [ - Row( + builder: (context, _, __) => widget.activityHeader != null + ? widget.activityHeader! + : isPinned! + ? const Column( children: [ - LMIcon( - type: LMIconType.svg, - assetPath: kAssetPinIcon, - color: LMThemeData.primary500, - size: 20, + Row( + children: [ + LMIcon( + type: LMIconType.svg, + assetPath: kAssetPinIcon, + color: LMThemeData.primary500, + size: 20, + ), + LMThemeData.kHorizontalPaddingMedium, + LMTextView( + text: "Pinned Post", + textStyle: TextStyle( + color: LMThemeData.primary500), + ) + ], ), - LMThemeData.kHorizontalPaddingMedium, - LMTextView( - text: "Pinned Post", - textStyle: TextStyle( - color: LMThemeData.primary500), - ) + LMThemeData.kVerticalPaddingMedium, ], - ), - LMThemeData.kVerticalPaddingMedium, - ], - ) - : const SizedBox(), + ) + : const SizedBox(), ), ValueListenableBuilder( valueListenable: rebuildPostWidget, @@ -452,7 +456,7 @@ class _SSPostWidgetState extends State { child: LMPostMedia( attachments: postDetails!.attachments!, borderRadius: 16.0, - backgroundColor: LMThemeData.kSecondary100, + backgroundColor: LMThemeData.kGrey1Color, documentIcon: const LMIcon( type: LMIconType.svg, assetPath: kAssetDocPDFIcon, @@ -466,6 +470,8 @@ class _SSPostWidgetState extends State { _videoController = initialiseVideoController; }, + boxFit: BoxFit.contain, + ), ), ) diff --git a/lib/src/widgets/widgets.dart b/lib/src/widgets/widgets.dart new file mode 100644 index 0000000..bbe79c6 --- /dev/null +++ b/lib/src/widgets/widgets.dart @@ -0,0 +1,2 @@ +export 'activity/activity_tile.dart'; +export 'activity/activity_widget.dart'; \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 8405cb9..506507d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,7 +26,7 @@ dependencies: overlay_support: lazy_load_scrollview: infinite_scroll_pagination: - device_info_plus: 9.1.0 + device_info_plus: ^9.1.1 permission_handler: image_picker: file_picker: @@ -37,7 +37,7 @@ dependencies: connectivity_plus: custom_pop_up_menu: ^1.2.4 flutter_no_internet_widget: ^1.0.0+18-dev.1 - extended_image: 8.1.0 + extended_image: 8.1.1 http: media_kit: ^1.1.10 # Primary package. media_kit_video: ^1.2.4 # For video rendering. @@ -83,6 +83,7 @@ flutter: - packages/likeminds_feed_ss_fl/assets/icons/like_filled.svg - packages/likeminds_feed_ss_fl/assets/icons/pdf.svg - packages/likeminds_feed_ss_fl/assets/icons/chat_lines.svg + - packages/likeminds_feed_ss_fl/assets/icons/mistery-box.svg # # For details regarding assets in packages, see From f60de44c98a89eca092ea9cdd08aa6e2d114f7cd Mon Sep 17 00:00:00 2001 From: Anuj Kumar <144224503+AnujLM@users.noreply.github.com> Date: Wed, 10 Jan 2024 12:35:52 +0530 Subject: [PATCH 2/5] chore: remove additional prints --- example/lib/cred_screen.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/example/lib/cred_screen.dart b/example/lib/cred_screen.dart index e9c08d2..c8f35da 100644 --- a/example/lib/cred_screen.dart +++ b/example/lib/cred_screen.dart @@ -289,8 +289,6 @@ class _CredScreenState extends State { uuid: _userIdController.text, ), ); - debugPrint( - "---------------${lmFeed!.userId!}-------------------"); Navigator.of(context).pushReplacement(route); }, child: Container( From 6f4b1ccb6f0c36d6e86200cdbbc016ecd10b4552 Mon Sep 17 00:00:00 2001 From: Anuj Kumar <144224503+AnujLM@users.noreply.github.com> Date: Wed, 10 Jan 2024 16:27:21 +0530 Subject: [PATCH 3/5] fix: fixed PR issues --- example/lib/cred_screen.dart | 1 - example/lib/screens/activity_screen.dart | 16 +- example/lib/screens/root_screen.dart | 9 +- .../flutter_typeahead-4.3.7/pubspec.yaml | 2 +- lib/src/utils/activity/activity_utils.dart | 26 ++ lib/src/views/activity/activity_feed.dart | 66 ++- lib/src/widgets/activity/activity_widget.dart | 436 ++++++++---------- 7 files changed, 265 insertions(+), 291 deletions(-) create mode 100644 lib/src/utils/activity/activity_utils.dart diff --git a/example/lib/cred_screen.dart b/example/lib/cred_screen.dart index c8f35da..cb251c8 100644 --- a/example/lib/cred_screen.dart +++ b/example/lib/cred_screen.dart @@ -286,7 +286,6 @@ class _CredScreenState extends State { // INIT - Get the LMFeed instance and pass the credentials (if any) builder: (context) => TabApp( feedWidget: lmFeed!, - uuid: _userIdController.text, ), ); Navigator.of(context).pushReplacement(route); diff --git a/example/lib/screens/activity_screen.dart b/example/lib/screens/activity_screen.dart index c27ea67..5479983 100644 --- a/example/lib/screens/activity_screen.dart +++ b/example/lib/screens/activity_screen.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:likeminds_feed_ss_fl/likeminds_feed_ss_fl.dart'; -import 'package:likeminds_feed_ss_sample/credentials/credentials.dart'; class ActivityScreen extends StatefulWidget { - const ActivityScreen({super.key, required this.uuid}); - final String uuid; + const ActivityScreen({ + super.key, + }); @override State createState() => _ActivityScreenState(); @@ -14,12 +14,10 @@ class _ActivityScreenState extends State { late String userId; @override void initState() { - const isProd = prodFlag; - userId = widget.uuid.isEmpty - ? isProd - ? CredsProd.botId - : CredsDev.botId - : widget.uuid; + userId = UserLocalPreference.instance + .fetchUserData() + .sdkClientInfo! + .userUniqueId; super.initState(); } diff --git a/example/lib/screens/root_screen.dart b/example/lib/screens/root_screen.dart index 79a775c..52e89b5 100644 --- a/example/lib/screens/root_screen.dart +++ b/example/lib/screens/root_screen.dart @@ -3,11 +3,9 @@ import 'package:likeminds_feed_ss_sample/screens/activity_screen.dart'; class TabApp extends StatefulWidget { final Widget feedWidget; - final String uuid; const TabApp({ super.key, required this.feedWidget, - required this.uuid, }); @override @@ -38,8 +36,8 @@ class _TabAppState extends State with TickerProviderStateMixin { setState(() {}); }, elevation: 10, - indicatorColor: Color(0xFF3B82F6), - backgroundColor: Color(0xFF3B82F6).withOpacity(0.1), + indicatorColor: const Color(0xFF3B82F6), + backgroundColor: const Color(0xFF3B82F6).withOpacity(0.1), destinations: const [ NavigationDestination( icon: Icon( @@ -69,8 +67,7 @@ class _TabAppState extends State with TickerProviderStateMixin { HomeScreen( feedWidget: widget.feedWidget, ), // First tab content - ActivityScreen( - uuid: widget.uuid, + const ActivityScreen( ), // Second tab content ], ), diff --git a/lib/packages/flutter_typeahead-4.3.7/pubspec.yaml b/lib/packages/flutter_typeahead-4.3.7/pubspec.yaml index 48c5eb1..299f86e 100644 --- a/lib/packages/flutter_typeahead-4.3.7/pubspec.yaml +++ b/lib/packages/flutter_typeahead-4.3.7/pubspec.yaml @@ -9,7 +9,7 @@ dependencies: flutter: sdk: flutter flutter_keyboard_visibility: ^5.4.0 - extended_text_field: 12.1.0 + extended_text_field: 13.0.0 dev_dependencies: flutter_test: diff --git a/lib/src/utils/activity/activity_utils.dart b/lib/src/utils/activity/activity_utils.dart new file mode 100644 index 0000000..db3294e --- /dev/null +++ b/lib/src/utils/activity/activity_utils.dart @@ -0,0 +1,26 @@ +import 'package:likeminds_feed/likeminds_feed.dart'; +import 'package:likeminds_feed_ui_fl/likeminds_feed_ui_fl.dart'; + +PostViewData postViewDataFromActivity(UserActivityItem activity) { + return activity.action == 7 + ? PostViewData.fromPost(post: activity.activityEntityData.postData!) + : (PostViewDataBuilder() + ..id(activity.activityEntityData.id) + ..isEdited(activity.activityEntityData.isEdited!) + ..text(activity.activityEntityData.text) + ..attachments(activity.activityEntityData.attachments!) + ..communityId(activity.activityEntityData.communityId) + ..isPinned(activity.activityEntityData.isPinned!) + ..topics(activity.activityEntityData.topics!) + ..userId(activity.activityEntityData.userId!) + ..likeCount(activity.activityEntityData.likesCount!) + ..commentCount(activity.activityEntityData.commentsCount!) + ..isSaved(activity.activityEntityData.isSaved!) + ..isLiked(activity.activityEntityData.isLiked!) + ..menuItems(activity.activityEntityData.menuItems!) + ..createdAt(DateTime.fromMillisecondsSinceEpoch( + activity.activityEntityData.createdAt)) + ..updatedAt(DateTime.fromMillisecondsSinceEpoch( + activity.activityEntityData.updatedAt!))) + .build(); +} \ No newline at end of file diff --git a/lib/src/views/activity/activity_feed.dart b/lib/src/views/activity/activity_feed.dart index 8f20b57..067fb19 100644 --- a/lib/src/views/activity/activity_feed.dart +++ b/lib/src/views/activity/activity_feed.dart @@ -5,6 +5,7 @@ import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:likeminds_feed/likeminds_feed.dart'; import 'package:likeminds_feed_ss_fl/src/blocs/comment/add_comment_reply/add_comment_reply_bloc.dart'; import 'package:likeminds_feed_ss_fl/src/blocs/comment/toggle_like_comment/toggle_like_comment_bloc.dart'; +import 'package:likeminds_feed_ss_fl/src/utils/activity/activity_utils.dart'; import 'package:likeminds_feed_ss_fl/src/utils/constants/assets_constants.dart'; import 'package:likeminds_feed_ss_fl/src/utils/constants/ui_constants.dart'; import 'package:likeminds_feed_ss_fl/src/utils/post/post_action_id.dart'; @@ -30,9 +31,17 @@ class _SSActivityFeedScreenState extends State { late final AddCommentReplyBloc _addCommentReplyBloc; late final ToggleLikeCommentBloc _toggleLikeCommentBloc; + String? userName; @override void initState() { + if (widget.uuid == + UserLocalPreference.instance + .fetchUserData() + .sdkClientInfo! + .userUniqueId) { + userName = 'You'; + } _addCommentReplyBloc = AddCommentReplyBloc(); _toggleLikeCommentBloc = ToggleLikeCommentBloc(); _pagingController.addPageRequestListener((pageKey) { @@ -64,20 +73,16 @@ class _SSActivityFeedScreenState extends State { } } - String getUserName(String actionBy) { - if (widget.uuid == - _userActivityResponse!.users![actionBy]!.sdkClientInfo!.userUniqueId) { - return 'You'; - } else { - return _userActivityResponse!.users![actionBy]!.name; - } + String setUserName( + GetUserActivityResponse activityResponse, String actionBy) { + return userName = activityResponse.users![actionBy]!.name; } - String getActivityTextWithoutName(String activityText, String actionBy) { - final String name = getUserName(actionBy); - return activityText.replaceFirst(name, ''); + String getActivityTextWithoutName(String activityText) { + return activityText.replaceFirst(userName!, ''); } + @override void dispose() { _addCommentReplyBloc.close(); @@ -156,30 +161,7 @@ class _SSActivityFeedScreenState extends State { ), ); }, itemBuilder: (context, item, index) { - //todo: change this - final PostViewData post = item.action == 7 - ? PostViewData.fromPost( - post: item.activityEntityData.postData!) - : (PostViewDataBuilder() - ..id(item.activityEntityData.id) - ..isEdited(item.activityEntityData.isEdited!) - ..text(item.activityEntityData.text) - ..attachments(item.activityEntityData.attachments!) - ..communityId(item.activityEntityData.communityId) - ..isPinned(item.activityEntityData.isPinned!) - ..topics(item.activityEntityData.topics!) - ..userId(item.activityEntityData.userId!) - ..likeCount(item.activityEntityData.likesCount!) - ..commentCount(item.activityEntityData.commentsCount!) - ..isSaved(item.activityEntityData.isSaved!) - ..isLiked(item.activityEntityData.isLiked!) - ..menuItems(item.activityEntityData.menuItems!) - ..createdAt(DateTime.fromMillisecondsSinceEpoch( - item.activityEntityData.createdAt)) - ..updatedAt(DateTime.fromMillisecondsSinceEpoch( - item.activityEntityData.updatedAt!))) - .build(); - + final PostViewData post = postViewDataFromActivity(item); final user = _userActivityResponse! .users![item.activityEntityData.userId]!; return Column( @@ -195,8 +177,13 @@ class _SSActivityFeedScreenState extends State { children: [ RichText( text: TextSpan( - text: - '${getUserName(_userActivityResponse!.activities!.elementAt(index).actionBy.first)}', + text: userName ?? + setUserName( + _userActivityResponse!, + _userActivityResponse!.activities! + .elementAt(index) + .actionBy + .first), style: const TextStyle( fontWeight: FontWeight.w600, fontSize: 14, @@ -204,8 +191,9 @@ class _SSActivityFeedScreenState extends State { ), children: [ TextSpan( - text: - '${getActivityTextWithoutName(_userActivityResponse!.activities!.elementAt(index).activityText, _userActivityResponse!.activities!.elementAt(index).actionBy.first)}', + text: getActivityTextWithoutName( + item.activityText, + ), style: const TextStyle( fontWeight: FontWeight.w400, fontSize: 14, @@ -215,7 +203,7 @@ class _SSActivityFeedScreenState extends State { ], ), ), - LMThemeData.kVerticalPaddingMedium, + LMThemeData.kVerticalPaddingMedium, const Divider( color: LMThemeData.onSurface, thickness: 1, diff --git a/lib/src/widgets/activity/activity_widget.dart b/lib/src/widgets/activity/activity_widget.dart index 4535a4b..f568c8f 100644 --- a/lib/src/widgets/activity/activity_widget.dart +++ b/lib/src/widgets/activity/activity_widget.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:likeminds_feed_ss_fl/likeminds_feed_ss_fl.dart'; +import 'package:likeminds_feed_ss_fl/src/utils/activity/activity_utils.dart'; import 'package:likeminds_feed_ss_fl/src/utils/constants/ui_constants.dart'; import 'package:likeminds_feed_ss_fl/src/views/activity/activity_feed.dart'; import 'package:likeminds_feed_ss_fl/src/views/post_detail_screen.dart'; @@ -18,11 +19,18 @@ class SSActivityWidget extends StatefulWidget { } class _SSActivityWidgetState extends State { - GetUserActivityResponse? _activityResponse; - final ValueNotifier _rebuildActivity = ValueNotifier(false); + late Future _activityResponse; + String? userName; @override void initState() { + if (widget.uuid == + UserLocalPreference.instance + .fetchUserData() + .sdkClientInfo! + .userUniqueId) { + userName = 'You'; + } loadActivity(); super.initState(); } @@ -33,24 +41,18 @@ class _SSActivityWidgetState extends State { ..page(1) ..pageSize(10)) .build(); - _activityResponse = await locator().getUserActivity( + _activityResponse = locator().getUserActivity( activityRequest, ); - _rebuildActivity.value = !_rebuildActivity.value; } - String getUserName(String actionBy) { - if (widget.uuid == - _activityResponse!.users![actionBy]!.sdkClientInfo!.userUniqueId) { - return 'You'; - } else { - return _activityResponse!.users![actionBy]!.name; - } + void setUserName(GetUserActivityResponse activityResponse, String actionBy) { + userName = activityResponse.users![actionBy]!.name; } - String getActivityTextWithoutName(String activityText, String actionBy) { - final String name = getUserName(actionBy); - return activityText.replaceFirst(name, ''); + String getActivityTextWithoutName( + String activityText) { + return activityText.replaceFirst(userName!, ''); } @override @@ -70,247 +72,211 @@ class _SSActivityWidgetState extends State { ), ), const Divider(color: LMThemeData.onSurface), - ValueListenableBuilder( - valueListenable: _rebuildActivity, - builder: (context, value, child) { - return _activityResponse == null - ? const Center( - child: LMLoader(), - ) - : Column( - children: [ - ListView.builder( - shrinkWrap: true, - itemCount: _activityResponse!.activities!.length <= 3 - ? _activityResponse?.activities?.length - : 3, - itemBuilder: (context, index) { - final activity = - _activityResponse!.activities![index]; - final PostViewData postData = activity.action == 7 - ? PostViewData.fromPost( - post: activity.activityEntityData.postData!) - : (PostViewDataBuilder() - ..id(activity.activityEntityData.id) - ..isEdited( - activity.activityEntityData.isEdited!) - ..text(activity.activityEntityData.text) - ..attachments(activity - .activityEntityData.attachments!) - ..communityId(activity - .activityEntityData.communityId) - ..isPinned( - activity.activityEntityData.isPinned!) - ..topics( - activity.activityEntityData.topics!) - ..userId( - activity.activityEntityData.userId!) - ..likeCount(activity - .activityEntityData.likesCount!) - ..commentCount(activity - .activityEntityData.commentsCount!) - ..isSaved( - activity.activityEntityData.isSaved!) - ..isLiked( - activity.activityEntityData.isLiked!) - ..menuItems(activity - .activityEntityData.menuItems!) - ..createdAt( - DateTime.fromMillisecondsSinceEpoch( - activity.activityEntityData - .createdAt)) - ..updatedAt( - DateTime.fromMillisecondsSinceEpoch( - activity.activityEntityData - .updatedAt!))) - .build(); - late final VideoPlayerController controller; - late final Future futureValue; - if (postData.attachments!.isNotEmpty && - mapIntToMediaType(postData - .attachments![0].attachmentType) == - MediaType.video) { - controller = VideoPlayerController.networkUrl( - Uri.parse(postData - .attachments![0].attachmentMeta.url!)); - futureValue = controller.initialize(); - } + FutureBuilder( + future: _activityResponse, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + final activityResponse = snapshot.data; + if (userName == null && + activityResponse!.activities!.isNotEmpty) { + setUserName(activityResponse, + activityResponse.activities!.first.actionBy.first); + } + return Column( + children: [ + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: activityResponse!.activities!.length <= 3 + ? activityResponse.activities?.length + : 3, + itemBuilder: (context, index) { + final activity = activityResponse.activities![index]; + final PostViewData postData = + postViewDataFromActivity(activity); + late final VideoPlayerController controller; + late final Future futureValue; + if (postData.attachments!.isNotEmpty && + mapIntToMediaType( + postData.attachments![0].attachmentType) == + MediaType.video) { + controller = VideoPlayerController.networkUrl( + Uri.parse(postData + .attachments![0].attachmentMeta.url!)); + futureValue = controller.initialize(); + } - return Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8.0), - child: Column( - children: [ - SSActivityTileWidget( - title: Row( - children: [ - RichText( - text: TextSpan( + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Column( + children: [ + SSActivityTileWidget( + title: Row( + children: [ + RichText( + text: TextSpan( + text: + userName!, + style: const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + color: LMThemeData.kGrey1Color, + ), + children: [ + TextSpan( text: - '${getUserName(activity.actionBy.first)}', + '${getActivityTextWithoutName(activity.activityText,)}', style: const TextStyle( - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w400, fontSize: 14, color: LMThemeData.kGrey1Color, ), - children: [ - TextSpan( - text: - '${getActivityTextWithoutName(activity.activityText, activity.actionBy.first)}', - style: const TextStyle( - fontWeight: FontWeight.w400, - fontSize: 14, - color: - LMThemeData.kGrey1Color, - ), - ), - ], - ), - ), - const Padding( - padding: EdgeInsets.only(left: 8.0), - child: CircleAvatar( - radius: 3, - backgroundColor: Colors.black, ), - ), - LMTextView( - text: - ' ${timeago.format(DateTime.fromMillisecondsSinceEpoch(_activityResponse!.activities![index].createdAt))}', - ), - ], + ], + ), ), - subtitle: Padding( - padding: const EdgeInsets.symmetric( - vertical: 2, + const Padding( + padding: EdgeInsets.only(left: 8.0), + child: CircleAvatar( + radius: 3, + backgroundColor: Colors.black, ), - child: ExpandableText(postData.text, - expandText: 'Read More', - maxLines: 2, onTagTap: (tag) { - debugPrint(tag); - }, onLinkTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - PostDetailScreen( - postId: postData.id, - ), - ), - ); - }, - style: const TextStyle( - fontWeight: FontWeight.w400, - fontSize: 14, - )), ), - trailing: postData - .attachments!.isNotEmpty && + LMTextView( + text: + ' ${timeago.format(DateTime.fromMillisecondsSinceEpoch(activityResponse.activities![index].createdAt))}', + ), + ], + ), + subtitle: Padding( + padding: const EdgeInsets.symmetric( + vertical: 2, + ), + child: ExpandableText(postData.text, + expandText: 'Read More', + maxLines: 2, onTagTap: (tag) { + debugPrint(tag); + }, onLinkTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PostDetailScreen( + postId: postData.id, + ), + ), + ); + }, + style: const TextStyle( + fontWeight: FontWeight.w400, + fontSize: 14, + )), + ), + trailing: postData.attachments!.isNotEmpty && + mapIntToMediaType(postData + .attachments![0] + .attachmentType) == + MediaType.image + ? ClipRRect( + borderRadius: BorderRadius.circular(4), + child: LMImage( + imageUrl: postData.attachments![0] + .attachmentMeta.url, + height: 64, + width: 64, + // borderRadius: 24, + boxFit: BoxFit.cover, + ), + ) + : postData.attachments!.isNotEmpty && mapIntToMediaType(postData .attachments![0] .attachmentType) == - MediaType.image - ? ClipRRect( - borderRadius: - BorderRadius.circular(4), - child: LMImage( - imageUrl: postData.attachments![0] - .attachmentMeta.url, - height: 64, - width: 64, - // borderRadius: 24, - boxFit: BoxFit.cover, - ), + MediaType.video + ? FutureBuilder( + future: futureValue, + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState.done) { + return ClipRRect( + borderRadius: + BorderRadius.circular(4), + child: SizedBox( + height: 64, + width: 64, + child: VideoPlayer( + controller, + ), + ), + ); + } else { + return const SizedBox( + height: 64, + width: 64, + child: LMPostMediaShimmer(), + ); + } + }, ) - : postData.attachments!.isNotEmpty && - mapIntToMediaType(postData - .attachments![0] - .attachmentType) == - MediaType.video - ? FutureBuilder( - future: futureValue, - builder: (context, snapshot) { - if (snapshot - .connectionState == - ConnectionState.done) { - return ClipRRect( - borderRadius: - BorderRadius.circular( - 4), - child: SizedBox( - height: 64, - width: 64, - child: VideoPlayer( - controller, - ), - ), - ); - } else { - return const SizedBox( - height: 64, - width: 64, - child:LMPostMediaShimmer(),); - } - }, - ) - : const SizedBox.shrink(), - onTap: () { - debugPrint('Activity Tapped'); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - PostDetailScreen( - postId: postData.id, - ), - ), - ); - }, - ), - if (index != - (_activityResponse!.activities!.length <= - 3 - ? (_activityResponse! - .activities!.length - - 1) - : 2)) - const Divider(color: LMThemeData.onSurface), - ], + : const SizedBox.shrink(), + onTap: () { + debugPrint('Activity Tapped'); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => PostDetailScreen( + postId: postData.id, + ), + ), + ); + }, ), - ); - }, - ), - const Divider(color: LMThemeData.onSurface), - LMTextButton( - text: const LMTextView( - text: 'View More Activity', - textStyle: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 15, - color: LMThemeData.kPrimaryColor), + if (index != + (activityResponse.activities!.length <= 3 + ? (activityResponse.activities!.length - + 1) + : 2)) + const Divider(color: LMThemeData.onSurface), + ], ), - icon: const LMIcon( - type: LMIconType.icon, - icon: Icons.arrow_forward, - color: LMThemeData.kPrimaryColor, + ); + }, + ), + const Divider(color: LMThemeData.onSurface), + LMTextButton( + text: const LMTextView( + text: 'View More Activity', + textStyle: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 15, + color: LMThemeData.kPrimaryColor), + ), + icon: const LMIcon( + type: LMIconType.icon, + icon: Icons.arrow_forward, + color: LMThemeData.kPrimaryColor, + ), + placement: LMIconPlacement.end, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SSActivityFeedScreen( + uuid: widget.uuid, + ), ), - placement: LMIconPlacement.end, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SSActivityFeedScreen( - uuid: widget.uuid, - ), - ), - ); - }, - ), - ], - ); + ); + }, + ), + ], + ); + } else { + return const Center(child: LMLoader()); + } }), const Divider(color: LMThemeData.onSurface) ], ); } } + + From 9c59de968cd74300b2cfd9fb67c3e37e03e1722e Mon Sep 17 00:00:00 2001 From: Anuj Kumar <144224503+AnujLM@users.noreply.github.com> Date: Wed, 10 Jan 2024 21:16:19 +0530 Subject: [PATCH 4/5] fix: Fixed for no user activity --- example/lib/screens/activity_screen.dart | 4 +- lib/src/utils/activity/activity_utils.dart | 125 ++++- lib/src/views/activity/activity_feed.dart | 50 +- lib/src/widgets/activity/activity_widget.dart | 451 +++++++++--------- 4 files changed, 338 insertions(+), 292 deletions(-) diff --git a/example/lib/screens/activity_screen.dart b/example/lib/screens/activity_screen.dart index 5479983..2762dfa 100644 --- a/example/lib/screens/activity_screen.dart +++ b/example/lib/screens/activity_screen.dart @@ -29,7 +29,9 @@ class _ActivityScreenState extends State { title: const Text('My Activity'), // backgroundColor: ColorTheme.backgroundColor, ), - body: SSActivityWidget(uuid: userId), + body: SSActivityWidget( + uuid: userId, + ), ); } } diff --git a/lib/src/utils/activity/activity_utils.dart b/lib/src/utils/activity/activity_utils.dart index db3294e..23b1304 100644 --- a/lib/src/utils/activity/activity_utils.dart +++ b/lib/src/utils/activity/activity_utils.dart @@ -1,26 +1,105 @@ import 'package:likeminds_feed/likeminds_feed.dart'; +import 'package:likeminds_feed_ss_fl/src/utils/constants/ui_constants.dart'; import 'package:likeminds_feed_ui_fl/likeminds_feed_ui_fl.dart'; +import 'package:flutter/material.dart'; -PostViewData postViewDataFromActivity(UserActivityItem activity) { - return activity.action == 7 - ? PostViewData.fromPost(post: activity.activityEntityData.postData!) - : (PostViewDataBuilder() - ..id(activity.activityEntityData.id) - ..isEdited(activity.activityEntityData.isEdited!) - ..text(activity.activityEntityData.text) - ..attachments(activity.activityEntityData.attachments!) - ..communityId(activity.activityEntityData.communityId) - ..isPinned(activity.activityEntityData.isPinned!) - ..topics(activity.activityEntityData.topics!) - ..userId(activity.activityEntityData.userId!) - ..likeCount(activity.activityEntityData.likesCount!) - ..commentCount(activity.activityEntityData.commentsCount!) - ..isSaved(activity.activityEntityData.isSaved!) - ..isLiked(activity.activityEntityData.isLiked!) - ..menuItems(activity.activityEntityData.menuItems!) - ..createdAt(DateTime.fromMillisecondsSinceEpoch( - activity.activityEntityData.createdAt)) - ..updatedAt(DateTime.fromMillisecondsSinceEpoch( - activity.activityEntityData.updatedAt!))) - .build(); -} \ No newline at end of file +class ActivityUtils { + static const String notificationTagRoute = + r'<<([^<>]+)\|route://([^<>]+)/([a-zA-Z-0-9_]+)>>'; + + static Map decodeNotificationString( + String string, String currentUserId) { + Map result = {}; + final Iterable matches = + RegExp(notificationTagRoute).allMatches(string); + for (final match in matches) { + String tag = match.group(1)!; + final String mid = match.group(2)!; + final String id = match.group(3)!; + if (id == currentUserId) { + tag = 'You'; + } + string = string.replaceAll('<<$tag|route://$mid/$id>>', '@$tag'); + result.addAll({tag: id}); + } + return result; + } + + static List extractNotificationTags( + String text, String currentUserId) { + List textSpans = []; + final Iterable matches = + RegExp(notificationTagRoute).allMatches(text); + int lastIndex = 0; + for (Match match in matches) { + int startIndex = match.start; + int endIndex = match.end; + String? link = match.group(0); + + if (lastIndex != startIndex) { + // Add a TextSpan for the preceding text + textSpans.add( + TextSpan( + text: text.substring(lastIndex, startIndex), + style: const TextStyle( + fontWeight: FontWeight.w400, + fontSize: 14, + color: LMThemeData.kGrey1Color, + ), + ), + ); + } + // Add a TextSpan for the URL + textSpans.add( + TextSpan( + text: decodeNotificationString(link!, currentUserId).keys.first, + style: const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + color: LMThemeData.kGrey1Color, + ), + ), + ); + + lastIndex = endIndex; + } + + if (lastIndex != text.length) { + // Add a TextSpan for the remaining text + textSpans.add(TextSpan( + text: text.substring(lastIndex), + style: const TextStyle( + fontWeight: FontWeight.w400, + fontSize: 14, + color: LMThemeData.kGrey1Color, + ), + )); + } + + return textSpans; + } + + static PostViewData postViewDataFromActivity(UserActivityItem activity) { + return activity.action == 7 + ? PostViewData.fromPost(post: activity.activityEntityData.postData!) + : (PostViewDataBuilder() + ..id(activity.activityEntityData.id) + ..isEdited(activity.activityEntityData.isEdited!) + ..text(activity.activityEntityData.text) + ..attachments(activity.activityEntityData.attachments!) + ..communityId(activity.activityEntityData.communityId) + ..isPinned(activity.activityEntityData.isPinned!) + ..topics(activity.activityEntityData.topics!) + ..userId(activity.activityEntityData.userId!) + ..likeCount(activity.activityEntityData.likesCount!) + ..commentCount(activity.activityEntityData.commentsCount!) + ..isSaved(activity.activityEntityData.isSaved!) + ..isLiked(activity.activityEntityData.isLiked!) + ..menuItems(activity.activityEntityData.menuItems!) + ..createdAt(DateTime.fromMillisecondsSinceEpoch( + activity.activityEntityData.createdAt)) + ..updatedAt(DateTime.fromMillisecondsSinceEpoch( + activity.activityEntityData.updatedAt!))) + .build(); + } +} diff --git a/lib/src/views/activity/activity_feed.dart b/lib/src/views/activity/activity_feed.dart index 067fb19..95bd889 100644 --- a/lib/src/views/activity/activity_feed.dart +++ b/lib/src/views/activity/activity_feed.dart @@ -31,17 +31,9 @@ class _SSActivityFeedScreenState extends State { late final AddCommentReplyBloc _addCommentReplyBloc; late final ToggleLikeCommentBloc _toggleLikeCommentBloc; - String? userName; @override void initState() { - if (widget.uuid == - UserLocalPreference.instance - .fetchUserData() - .sdkClientInfo! - .userUniqueId) { - userName = 'You'; - } _addCommentReplyBloc = AddCommentReplyBloc(); _toggleLikeCommentBloc = ToggleLikeCommentBloc(); _pagingController.addPageRequestListener((pageKey) { @@ -73,16 +65,6 @@ class _SSActivityFeedScreenState extends State { } } - String setUserName( - GetUserActivityResponse activityResponse, String actionBy) { - return userName = activityResponse.users![actionBy]!.name; - } - - String getActivityTextWithoutName(String activityText) { - return activityText.replaceFirst(userName!, ''); - } - - @override void dispose() { _addCommentReplyBloc.close(); @@ -161,7 +143,8 @@ class _SSActivityFeedScreenState extends State { ), ); }, itemBuilder: (context, item, index) { - final PostViewData post = postViewDataFromActivity(item); + final PostViewData post = + ActivityUtils.postViewDataFromActivity(item); final user = _userActivityResponse! .users![item.activityEntityData.userId]!; return Column( @@ -177,30 +160,11 @@ class _SSActivityFeedScreenState extends State { children: [ RichText( text: TextSpan( - text: userName ?? - setUserName( - _userActivityResponse!, - _userActivityResponse!.activities! - .elementAt(index) - .actionBy - .first), - style: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: LMThemeData.kGrey1Color, - ), - children: [ - TextSpan( - text: getActivityTextWithoutName( - item.activityText, - ), - style: const TextStyle( - fontWeight: FontWeight.w400, - fontSize: 14, - color: LMThemeData.kGrey1Color, - ), - ), - ], + children: ActivityUtils.extractNotificationTags( + _userActivityResponse!.activities! + .elementAt(index) + .activityText, + widget.uuid), ), ), LMThemeData.kVerticalPaddingMedium, diff --git a/lib/src/widgets/activity/activity_widget.dart b/lib/src/widgets/activity/activity_widget.dart index f568c8f..0959e58 100644 --- a/lib/src/widgets/activity/activity_widget.dart +++ b/lib/src/widgets/activity/activity_widget.dart @@ -20,17 +20,9 @@ class SSActivityWidget extends StatefulWidget { class _SSActivityWidgetState extends State { late Future _activityResponse; - String? userName; @override void initState() { - if (widget.uuid == - UserLocalPreference.instance - .fetchUserData() - .sdkClientInfo! - .userUniqueId) { - userName = 'You'; - } loadActivity(); super.initState(); } @@ -46,237 +38,246 @@ class _SSActivityWidgetState extends State { ); } - void setUserName(GetUserActivityResponse activityResponse, String actionBy) { - userName = activityResponse.users![actionBy]!.name; - } - - String getActivityTextWithoutName( - String activityText) { - return activityText.replaceFirst(userName!, ''); - } - @override Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Divider(color: LMThemeData.onSurface), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 8.0), - child: LMTextView( - text: 'Activity', - textStyle: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, + return Theme( + data: LMThemeData.suraasaTheme, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Divider(color: LMThemeData.onSurface), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 8.0), + child: LMTextView( + text: 'Activity', + textStyle: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), ), ), - ), - const Divider(color: LMThemeData.onSurface), - FutureBuilder( - future: _activityResponse, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - final activityResponse = snapshot.data; - if (userName == null && - activityResponse!.activities!.isNotEmpty) { - setUserName(activityResponse, - activityResponse.activities!.first.actionBy.first); - } - return Column( - children: [ - ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: activityResponse!.activities!.length <= 3 - ? activityResponse.activities?.length - : 3, - itemBuilder: (context, index) { - final activity = activityResponse.activities![index]; - final PostViewData postData = - postViewDataFromActivity(activity); - late final VideoPlayerController controller; - late final Future futureValue; - if (postData.attachments!.isNotEmpty && - mapIntToMediaType( - postData.attachments![0].attachmentType) == - MediaType.video) { - controller = VideoPlayerController.networkUrl( - Uri.parse(postData - .attachments![0].attachmentMeta.url!)); - futureValue = controller.initialize(); - } + const Divider(color: LMThemeData.onSurface), + FutureBuilder( + future: _activityResponse, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + final activityResponse = snapshot.data; + return activityResponse!.activities!.isEmpty + ? SizedBox.shrink() + : Column( + children: [ + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: + activityResponse.activities!.length <= 3 + ? activityResponse.activities?.length + : 3, + itemBuilder: (context, index) { + final activity = + activityResponse.activities![index]; + final PostViewData postData = + ActivityUtils.postViewDataFromActivity( + activity); + late final VideoPlayerController controller; + late final Future futureValue; + if (postData.attachments!.isNotEmpty && + mapIntToMediaType(postData + .attachments![0].attachmentType) == + MediaType.video) { + controller = VideoPlayerController.networkUrl( + Uri.parse(postData.attachments![0] + .attachmentMeta.url!)); + futureValue = controller.initialize(); + } - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Column( - children: [ - SSActivityTileWidget( - title: Row( - children: [ - RichText( - text: TextSpan( - text: - userName!, - style: const TextStyle( - fontWeight: FontWeight.w600, - fontSize: 14, - color: LMThemeData.kGrey1Color, - ), - children: [ - TextSpan( - text: - '${getActivityTextWithoutName(activity.activityText,)}', - style: const TextStyle( - fontWeight: FontWeight.w400, - fontSize: 14, - color: LMThemeData.kGrey1Color, - ), - ), - ], - ), - ), - const Padding( - padding: EdgeInsets.only(left: 8.0), - child: CircleAvatar( - radius: 3, - backgroundColor: Colors.black, - ), - ), - LMTextView( - text: - ' ${timeago.format(DateTime.fromMillisecondsSinceEpoch(activityResponse.activities![index].createdAt))}', - ), - ], - ), - subtitle: Padding( + return Padding( padding: const EdgeInsets.symmetric( - vertical: 2, - ), - child: ExpandableText(postData.text, - expandText: 'Read More', - maxLines: 2, onTagTap: (tag) { - debugPrint(tag); - }, onLinkTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PostDetailScreen( - postId: postData.id, + horizontal: 8.0), + child: Column( + children: [ + SSActivityTileWidget( + title: Row( + children: [ + ConstrainedBox( + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context) + .size + .width * + 0.6, + ), + child: RichText( + maxLines: 1, + overflow: TextOverflow.ellipsis, + text: TextSpan( + children: ActivityUtils + .extractNotificationTags( + snapshot + .data!.activities! + .elementAt(index) + .activityText, + widget.uuid), + ), + ), + ), + const Padding( + padding: + EdgeInsets.only(left: 8.0), + child: CircleAvatar( + radius: 3, + backgroundColor: Colors.black, + ), + ), + LMTextView( + text: + ' ${timeago.format(DateTime.fromMillisecondsSinceEpoch(activityResponse.activities![index].createdAt))}', + ), + ], ), - ), - ); - }, - style: const TextStyle( - fontWeight: FontWeight.w400, - fontSize: 14, - )), - ), - trailing: postData.attachments!.isNotEmpty && - mapIntToMediaType(postData - .attachments![0] - .attachmentType) == - MediaType.image - ? ClipRRect( - borderRadius: BorderRadius.circular(4), - child: LMImage( - imageUrl: postData.attachments![0] - .attachmentMeta.url, - height: 64, - width: 64, - // borderRadius: 24, - boxFit: BoxFit.cover, + subtitle: Padding( + padding: const EdgeInsets.symmetric( + vertical: 2, + ), + child: ExpandableText(postData.text, + expandText: 'Read More', + maxLines: 2, onTagTap: (tag) { + debugPrint(tag); + }, onLinkTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + PostDetailScreen( + postId: postData.id, + ), + ), + ); + }, + style: const TextStyle( + fontWeight: FontWeight.w400, + fontSize: 14, + )), ), - ) - : postData.attachments!.isNotEmpty && - mapIntToMediaType(postData - .attachments![0] - .attachmentType) == - MediaType.video - ? FutureBuilder( - future: futureValue, - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState.done) { - return ClipRRect( - borderRadius: - BorderRadius.circular(4), - child: SizedBox( - height: 64, - width: 64, - child: VideoPlayer( - controller, - ), - ), - ); - } else { - return const SizedBox( + trailing: postData + .attachments!.isNotEmpty && + mapIntToMediaType(postData + .attachments![0] + .attachmentType) == + MediaType.image + ? ClipRRect( + borderRadius: + BorderRadius.circular(4), + child: LMImage( + imageUrl: postData + .attachments![0] + .attachmentMeta + .url, height: 64, width: 64, - child: LMPostMediaShimmer(), - ); - } - }, - ) - : const SizedBox.shrink(), - onTap: () { - debugPrint('Activity Tapped'); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PostDetailScreen( - postId: postData.id, + // borderRadius: 24, + boxFit: BoxFit.cover, + ), + ) + : postData.attachments! + .isNotEmpty && + mapIntToMediaType(postData + .attachments![0] + .attachmentType) == + MediaType.video + ? FutureBuilder( + future: futureValue, + builder: + (context, snapshot) { + if (snapshot + .connectionState == + ConnectionState + .done) { + return ClipRRect( + borderRadius: + BorderRadius + .circular(4), + child: SizedBox( + height: 64, + width: 64, + child: VideoPlayer( + controller, + ), + ), + ); + } else { + return const SizedBox( + height: 64, + width: 64, + child: + LMPostMediaShimmer(), + ); + } + }, + ) + : const SizedBox.shrink(), + onTap: () { + debugPrint('Activity Tapped'); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + PostDetailScreen( + postId: postData.id, + ), + ), + ); + }, ), - ), - ); - }, + if (index != + (activityResponse + .activities!.length <= + 3 + ? (activityResponse + .activities!.length - + 1) + : 2)) + const Divider( + color: LMThemeData.onSurface), + ], + ), + ); + }, + ), + const Divider(color: LMThemeData.onSurface), + LMTextButton( + text: const LMTextView( + text: 'View More Activity', + textStyle: TextStyle( + fontWeight: FontWeight.w500, + fontSize: 15, + color: LMThemeData.kPrimaryColor), ), - if (index != - (activityResponse.activities!.length <= 3 - ? (activityResponse.activities!.length - - 1) - : 2)) - const Divider(color: LMThemeData.onSurface), - ], - ), - ); - }, - ), - const Divider(color: LMThemeData.onSurface), - LMTextButton( - text: const LMTextView( - text: 'View More Activity', - textStyle: TextStyle( - fontWeight: FontWeight.w500, - fontSize: 15, - color: LMThemeData.kPrimaryColor), - ), - icon: const LMIcon( - type: LMIconType.icon, - icon: Icons.arrow_forward, - color: LMThemeData.kPrimaryColor, - ), - placement: LMIconPlacement.end, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SSActivityFeedScreen( - uuid: widget.uuid, + icon: const LMIcon( + type: LMIconType.icon, + icon: Icons.arrow_forward, + color: LMThemeData.kPrimaryColor, + ), + placement: LMIconPlacement.end, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SSActivityFeedScreen( + uuid: widget.uuid, + ), + ), + ); + }, ), - ), + ], ); - }, - ), - ], - ); - } else { - return const Center(child: LMLoader()); - } - }), - const Divider(color: LMThemeData.onSurface) - ], + } else { + return const Center(child: LMLoader()); + } + }), + const Divider(color: LMThemeData.onSurface) + ], + ), ); } } - - From 7bd803708beda0a96ac7b33d7491bf6253c36137 Mon Sep 17 00:00:00 2001 From: Anuj Kumar <144224503+AnujLM@users.noreply.github.com> Date: Wed, 10 Jan 2024 21:23:15 +0530 Subject: [PATCH 5/5] version update --- example/pubspec.yaml | 2 +- pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/example/pubspec.yaml b/example/pubspec.yaml index e7f582b..ab28dce 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.4.0 +version: 1.4.1 environment: sdk: ">=3.0.0 <4.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 506507d..41d1d3a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: likeminds_feed_ss_fl description: A new Flutter package project. -version: 1.4.0 +version: 1.4.1 publish_to: none homepage: "https://likeminds.community/" @@ -53,7 +53,7 @@ dependencies: path: ../LikeMinds-Flutter-Feed-UI likeminds_feed: - 1.6.5 + 1.6.6 # path: ../LikeMinds-Flutter-Feed-SDK dependency_override: