|
@@ -1,16 +1,23 @@
|
|
import 'package:cpt_community/router/page/community_page_router.dart';
|
|
import 'package:cpt_community/router/page/community_page_router.dart';
|
|
|
|
+import 'package:cs_resources/generated/assets.dart';
|
|
import 'package:cs_resources/theme/app_colors_theme.dart';
|
|
import 'package:cs_resources/theme/app_colors_theme.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:auto_route/auto_route.dart';
|
|
import 'package:auto_route/auto_route.dart';
|
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
|
|
+import 'package:plugin_basic/provider/app_config/app_config.dart';
|
|
import 'package:router/ext/auto_router_extensions.dart';
|
|
import 'package:router/ext/auto_router_extensions.dart';
|
|
import 'package:shared/utils/color_utils.dart';
|
|
import 'package:shared/utils/color_utils.dart';
|
|
import 'package:shared/utils/log_utils.dart';
|
|
import 'package:shared/utils/log_utils.dart';
|
|
import 'package:widgets/ext/ex_widget.dart';
|
|
import 'package:widgets/ext/ex_widget.dart';
|
|
|
|
+import 'package:widgets/load_state_layout.dart';
|
|
import 'package:widgets/my_appbar.dart';
|
|
import 'package:widgets/my_appbar.dart';
|
|
import 'package:widgets/my_button.dart';
|
|
import 'package:widgets/my_button.dart';
|
|
|
|
+import 'package:widgets/my_like_button.dart';
|
|
|
|
+import 'package:widgets/my_load_image.dart';
|
|
import 'package:widgets/my_text_view.dart';
|
|
import 'package:widgets/my_text_view.dart';
|
|
|
|
+import 'package:widgets/widget_export.dart';
|
|
|
|
+import 'package:widgets/my_button.dart';
|
|
|
|
|
|
import '../../../components/newfeed_card_header.dart';
|
|
import '../../../components/newfeed_card_header.dart';
|
|
import '../../../components/newsfeed_card_content.dart';
|
|
import '../../../components/newsfeed_card_content.dart';
|
|
@@ -38,9 +45,11 @@ class NewsfeedDetailPage extends HookConsumerWidget {
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final vm = ref.read(newsfeedDetailVmProvider.notifier);
|
|
final vm = ref.read(newsfeedDetailVmProvider.notifier);
|
|
final state = ref.watch(newsfeedDetailVmProvider);
|
|
final state = ref.watch(newsfeedDetailVmProvider);
|
|
|
|
+ GlobalKey _likeButtonKey = GlobalKey<MyLikeButtonState>();
|
|
|
|
+
|
|
useEffect((){
|
|
useEffect((){
|
|
|
|
|
|
-
|
|
+ Future.microtask(() => vm.initPageData(id: id));
|
|
return () {
|
|
return () {
|
|
|
|
|
|
};
|
|
};
|
|
@@ -51,113 +60,154 @@ class NewsfeedDetailPage extends HookConsumerWidget {
|
|
appBar: MyAppBar.appBar(
|
|
appBar: MyAppBar.appBar(
|
|
context,
|
|
context,
|
|
"News Feed Detail",
|
|
"News Feed Detail",
|
|
- backgroundColor: context.appColors.whiteBG,
|
|
+ backgroundColor: context.appColors.backgroundWhite,
|
|
),
|
|
),
|
|
backgroundColor: ColorUtils.string2Color("#F2F3F6"),
|
|
backgroundColor: ColorUtils.string2Color("#F2F3F6"),
|
|
body: Column(
|
|
body: Column(
|
|
- children: [
|
|
+ mainAxisSize: MainAxisSize.max,
|
|
- _buildTopCard(context, ref),
|
|
+ children:[
|
|
-
|
|
+ Expanded(
|
|
- Expanded(child: _buildCommentListCard(context, ref)),
|
|
+ child: EasyRefresh(
|
|
-
|
|
+ controller: vm.refreshController,
|
|
- Container(
|
|
+
|
|
- color: ColorUtils.string2Color("#2956B7"),
|
|
+ onLoad: () async{
|
|
- child: Row(
|
|
+ Log.d("----onLoad");
|
|
- children: [
|
|
+ vm.loadMore();
|
|
- Expanded(
|
|
+ },
|
|
- child: MyButton(
|
|
+
|
|
- minHeight: 50,
|
|
+ onRefresh: () async{
|
|
- text: 'Like',
|
|
+ Log.d("----onRefresh");
|
|
- textColor: Colors.white,
|
|
+ vm.onRefresh();
|
|
- onPressed: () {},
|
|
+ },
|
|
- )
|
|
+ child: LoadStateLayout(
|
|
- )
|
|
+ state: state.loadingState,
|
|
- ]
|
|
+ errorMessage: state.errorMessage,
|
|
- )
|
|
+ errorRetry: () {
|
|
- )
|
|
+ vm.retryRequest();
|
|
- ],
|
|
+ },
|
|
- ),
|
|
+ successSliverWidget: [
|
|
|
|
+ SliverList(
|
|
|
|
+ delegate: SliverChildListDelegate(
|
|
|
|
+ [
|
|
|
|
+ _buildTopCard(context, ref),
|
|
|
|
+ ConstrainedBox(
|
|
|
|
+ constraints: BoxConstraints(
|
|
|
|
+ minHeight: MediaQuery.of(context).size.height - 250 - 150,
|
|
|
|
+ ),
|
|
|
|
+ child: _buildCommentListCard(context, ref),
|
|
|
|
+ )
|
|
|
|
+ ]
|
|
|
|
+ ),
|
|
|
|
+ )
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ _buildBottomActionSection(context, ref, _likeButtonKey),
|
|
|
|
+ ]
|
|
|
|
+ )
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
Widget _buildTopCard(BuildContext context, WidgetRef ref){
|
|
Widget _buildTopCard(BuildContext context, WidgetRef ref){
|
|
final vm = ref.read(newsfeedDetailVmProvider.notifier);
|
|
final vm = ref.read(newsfeedDetailVmProvider.notifier);
|
|
final state = ref.watch(newsfeedDetailVmProvider);
|
|
final state = ref.watch(newsfeedDetailVmProvider);
|
|
- return Container(
|
|
+ return Stack(
|
|
- width: double.infinity,
|
|
+ children: [
|
|
-
|
|
+ Container(
|
|
- child: Stack(
|
|
+ margin: const EdgeInsets.only(left: 15, right: 15,top: 14,bottom: 14),
|
|
- children: [
|
|
+ padding: const EdgeInsets.only(left: 15, right: 15,top: 17,bottom: 17),
|
|
- Container(
|
|
+ decoration: BoxDecoration(
|
|
- margin: const EdgeInsets.only(left: 15, right: 15,top: 14,bottom: 14),
|
|
+ color: context.appColors.textWhite,
|
|
- color: Colors.white,
|
|
+ borderRadius: BorderRadius.circular(10),
|
|
- padding: const EdgeInsets.only(left: 15, right: 15,top: 17,bottom: 17),
|
|
+ boxShadow: [
|
|
- height: 280,
|
|
+ BoxShadow(
|
|
- child: Column(
|
|
+ color: ColorUtils.string2Color("#E4E7EB").withOpacity(0.5),
|
|
- mainAxisAlignment: MainAxisAlignment.center,
|
|
+ spreadRadius: 0,
|
|
- crossAxisAlignment: CrossAxisAlignment.start,
|
|
+ blurRadius: 4,
|
|
- children: [
|
|
+ offset: const Offset(0, 4),
|
|
-
|
|
+ ),
|
|
- NewsFeedCardHeader(
|
|
+ ]
|
|
- key: UniqueKey(),
|
|
|
|
- title: state?.detailInfo!['title'],
|
|
|
|
- avator: state?.detailInfo['avator'],
|
|
|
|
- time: state?.detailInfo['time'],
|
|
|
|
- ),
|
|
|
|
- const SizedBox(height: 15),
|
|
|
|
-
|
|
|
|
- Expanded(
|
|
|
|
- child: NewsFeedCardContent(
|
|
|
|
- key: UniqueKey(),
|
|
|
|
- content: state.detailInfo['content'],
|
|
|
|
- imageUrls: state.detailInfo['imageUrls'],
|
|
|
|
- ),
|
|
|
|
- ),
|
|
|
|
- const SizedBox(height: 26),
|
|
|
|
- ]
|
|
|
|
- ),
|
|
|
|
),
|
|
),
|
|
-
|
|
+ child: Column(
|
|
- Visibility(
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
- visible: !state.detailInfo['isFollow'],
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
- child: Positioned(
|
|
+ children: [
|
|
- right: 40,
|
|
+
|
|
- top: 35,
|
|
+ NewsFeedCardHeader(
|
|
- child: Container(
|
|
+ key: UniqueKey(),
|
|
- width: 83.5,
|
|
+ title: state?.detailInfo!['title'],
|
|
- height: 45.5,
|
|
+ avator: state?.detailInfo['avator'],
|
|
- alignment: Alignment.center,
|
|
+ time: state?.detailInfo['time'],
|
|
-
|
|
+ ),
|
|
-
|
|
+ const SizedBox(height: 15),
|
|
-
|
|
+
|
|
-
|
|
+ NewsFeedCardContent(
|
|
- child: MyButton(
|
|
+ key: UniqueKey(),
|
|
- text: '+Follow',
|
|
+ content: state.detailInfo['content'],
|
|
- textColor: Colors.white,
|
|
+ imageUrls: state.detailInfo['imageUrls'],
|
|
- backgroundColor: ColorUtils.string2Color('#4161D0'),
|
|
+ textMaxLines: 5000,
|
|
- radius: 8,
|
|
+ ),
|
|
- minHeight: 27.5,
|
|
+ const SizedBox(height: 26),
|
|
- padding: const EdgeInsets.only(left: 5, right: 5,top:9,bottom:9),
|
|
+ ]
|
|
- fontWeight: FontWeight.w400,
|
|
+ ),
|
|
- fontSize: 14,
|
|
+ ),
|
|
- onPressed: (){
|
|
+
|
|
-
|
|
+ Visibility(
|
|
- },
|
|
+ visible: !state.detailInfo['isFollow'],
|
|
- ),
|
|
+ child: Positioned(
|
|
- )
|
|
+ right: 40,
|
|
- ),
|
|
+ top: 35,
|
|
- )
|
|
+ child: Container(
|
|
- ],
|
|
+ width: 83.5,
|
|
- ),
|
|
+ height: 45.5,
|
|
|
|
+ alignment: Alignment.center,
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ child: MyButton(
|
|
|
|
+ text: '+Follow',
|
|
|
|
+ textColor: Colors.white,
|
|
|
|
+ backgroundColor: ColorUtils.string2Color('#4161D0'),
|
|
|
|
+ radius: 8,
|
|
|
|
+ minHeight: 27.5,
|
|
|
|
+ padding: const EdgeInsets.only(left: 5, right: 5,top:9,bottom:9),
|
|
|
|
+ fontWeight: FontWeight.w400,
|
|
|
|
+ fontSize: 14,
|
|
|
|
+ onPressed: (){
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ )
|
|
|
|
+ ),
|
|
|
|
+ )
|
|
|
|
+ ],
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
Widget _buildCommentListCard(BuildContext context, WidgetRef ref){
|
|
Widget _buildCommentListCard(BuildContext context, WidgetRef ref){
|
|
|
|
+ final vm = ref.read(newsfeedDetailVmProvider.notifier);
|
|
return Container(
|
|
return Container(
|
|
- color: Colors.white,
|
|
|
|
margin: const EdgeInsets.only(left: 15, right: 15,top: 18,bottom: 18),
|
|
margin: const EdgeInsets.only(left: 15, right: 15,top: 18,bottom: 18),
|
|
|
|
+ padding: const EdgeInsets.only(bottom: 30),
|
|
|
|
+ decoration: BoxDecoration(
|
|
|
|
+ color: context.appColors.textWhite,
|
|
|
|
+ borderRadius: BorderRadius.circular(10),
|
|
|
|
+ boxShadow: [
|
|
|
|
+ BoxShadow(
|
|
|
|
+ color: ColorUtils.string2Color("#E4E7EB").withOpacity(0.5),
|
|
|
|
+ spreadRadius: 0,
|
|
|
|
+ blurRadius: 4,
|
|
|
|
+ offset: const Offset(0, 4),
|
|
|
|
+ ),
|
|
|
|
+ ]
|
|
|
|
+ ),
|
|
child: Column(
|
|
child: Column(
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
children: [
|
|
|
|
+
|
|
Row(
|
|
Row(
|
|
children: [
|
|
children: [
|
|
Expanded(
|
|
Expanded(
|
|
@@ -167,17 +217,58 @@ class NewsfeedDetailPage extends HookConsumerWidget {
|
|
children: [
|
|
children: [
|
|
MyTextView('Comments', textColor: ColorUtils.string2Color("#2956B7"), fontSize: 15, isFontLight: true,),
|
|
MyTextView('Comments', textColor: ColorUtils.string2Color("#2956B7"), fontSize: 15, isFontLight: true,),
|
|
const SizedBox(width: 5,),
|
|
const SizedBox(width: 5,),
|
|
- MyTextView('95', textColor: ColorUtils.string2Color("#2956B7"), fontSize: 15, isFontLight: true,),
|
|
+ MyTextView('(95)', textColor: ColorUtils.string2Color("#2956B7"), fontSize: 15, isFontLight: true,),
|
|
]
|
|
]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
- )
|
|
+ ),
|
|
|
|
+
|
|
|
|
+ Expanded(
|
|
|
|
+ child: Container(
|
|
|
|
+ padding: const EdgeInsets.only(right: 20),
|
|
|
|
+ child: Row(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.end,
|
|
|
|
+ children: [
|
|
|
|
+ const MyAssetImage(
|
|
|
|
+ Assets.communityLikeActive,
|
|
|
|
+ width: 15,
|
|
|
|
+ height: 15,
|
|
|
|
+ ),
|
|
|
|
+ const SizedBox(width: 5,),
|
|
|
|
+ MyTextView(
|
|
|
|
+ '105K',
|
|
|
|
+ textColor: ColorUtils.string2Color("#767676"),
|
|
|
|
+ fontSize: 14,
|
|
|
|
+ isFontLight: true,
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ )
|
|
],
|
|
],
|
|
),
|
|
),
|
|
- const Expanded(
|
|
+
|
|
- child: Row(
|
|
+
|
|
- children: [
|
|
+ Container(
|
|
- Text("fsdf"),
|
|
+ height: 1,
|
|
|
|
+ color: context.appColors.dividerDefault,
|
|
|
|
+ ),
|
|
|
|
+
|
|
|
|
+ Padding(
|
|
|
|
+ padding: const EdgeInsets.only(top: 16),
|
|
|
|
+ child: Column(
|
|
|
|
+ children: (vm.state.list.isNotEmpty )? vm.state.list.asMap().entries.map((entry) {
|
|
|
|
+ final item = entry.value;
|
|
|
|
+ final index = entry.key;
|
|
|
|
+ final lastIdx = vm.state.list.length - 1;
|
|
|
|
+ return _buildCommentItem(context, ref, item, index, lastIdx);
|
|
|
|
+ }).toList(): [
|
|
|
|
+ Center(
|
|
|
|
+ child: SizedBox(
|
|
|
|
+ height: 200,
|
|
|
|
+ child: MyTextView("NO DATA"),
|
|
|
|
+ ),
|
|
|
|
+ )
|
|
],
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
@@ -185,4 +276,165 @@ class NewsfeedDetailPage extends HookConsumerWidget {
|
|
),
|
|
),
|
|
).borderRadius(all:8);
|
|
).borderRadius(all:8);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ Widget _buildCommentItem(BuildContext context, WidgetRef ref, item, index, lastIdx){
|
|
|
|
+ final vm = ref.read(newsfeedDetailVmProvider.notifier);
|
|
|
|
+ final state = ref.watch(newsfeedDetailVmProvider);
|
|
|
|
+ return Container(
|
|
|
|
+ padding: const EdgeInsets.only(left: 20,right: 20),
|
|
|
|
+ margin: EdgeInsets.only(top: index> 0? 16: 0),
|
|
|
|
+ child: Row(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.start,
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
+ mainAxisSize: MainAxisSize.max,
|
|
|
|
+ children: [
|
|
|
|
+ MyLoadImage(
|
|
|
|
+ item['avator'],
|
|
|
|
+ width: 43,
|
|
|
|
+ height: 43,
|
|
|
|
+ isCircle: true,
|
|
|
|
+ fit: BoxFit.cover,
|
|
|
|
+ ).onTap(() {
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }),
|
|
|
|
+ Expanded(
|
|
|
|
+ child: Container(
|
|
|
|
+ padding: const EdgeInsets.only(left:15, right: 0),
|
|
|
|
+
|
|
|
|
+ child: Column(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.start,
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
+ children: [
|
|
|
|
+ MyTextView(
|
|
|
|
+ item['userName'],
|
|
|
|
+ isFontRegular: true,
|
|
|
|
+ fontSize: 14,
|
|
|
|
+ textColor: ColorUtils.string2Color('#2956B7'),
|
|
|
|
+ maxLines: 1,
|
|
|
|
+ isTextEllipsis: true,
|
|
|
|
+ ),
|
|
|
|
+ MyTextView(
|
|
|
|
+ item['time'],
|
|
|
|
+ isFontLight: true,
|
|
|
|
+ fontSize: 12,
|
|
|
|
+ marginTop: 10,
|
|
|
|
+ textColor: ColorUtils.string2Color('#767676'),
|
|
|
|
+ maxLines: 1,
|
|
|
|
+ isTextEllipsis: true,
|
|
|
|
+ ),
|
|
|
|
+ MyTextView(
|
|
|
|
+ item['content'],
|
|
|
|
+ isFontLight: true,
|
|
|
|
+ fontSize: 15,
|
|
|
|
+ marginTop: 10,
|
|
|
|
+ textColor: context.appColors.textBlack,
|
|
|
|
+ maxLines: null,
|
|
|
|
+ isTextEllipsis: false,
|
|
|
|
+ ),
|
|
|
|
+
|
|
|
|
+ const SizedBox(height: 15,),
|
|
|
|
+
|
|
|
|
+ index!=lastIdx?Container(height: 1, color: context.appColors.dividerDefault):const SizedBox.shrink(),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ Widget _buildBottomActionSection(BuildContext context, WidgetRef ref , _likeButtonKey){
|
|
|
|
+ final state = ref.watch(newsfeedDetailVmProvider);
|
|
|
|
+ final vm = ref.read(newsfeedDetailVmProvider.notifier);
|
|
|
|
+ bool isLike = state.detailInfo['isLike'];
|
|
|
|
+ return SafeArea(
|
|
|
|
+ child: Visibility(
|
|
|
|
+ visible: state.loadingState == LoadState.State_Success,
|
|
|
|
+ child: Container(
|
|
|
|
+ height: 60,
|
|
|
|
+ width: MediaQuery.of(context).size.width,
|
|
|
|
+ color: context.appColors.textPrimary,
|
|
|
|
+ child: Row(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
|
+ children: [
|
|
|
|
+ Expanded(
|
|
|
|
+ child: Row(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
|
+ children: [
|
|
|
|
+ Container(
|
|
|
|
+ alignment: Alignment.center,
|
|
|
|
+ padding: const EdgeInsets.only(left: 10,right: 10),
|
|
|
|
+ child: Wrap(
|
|
|
|
+ children: [
|
|
|
|
+ MyLikeButton(
|
|
|
|
+ key: _likeButtonKey,
|
|
|
|
+ isLiked: false,
|
|
|
|
+ isCustomIcon: true,
|
|
|
|
+ customIconWidth: 20,
|
|
|
|
+ customIconHeight: 18,
|
|
|
|
+ customIconActiveAssets: Assets.communityLikeActive,
|
|
|
|
+ customIconUnActiveAssets: Assets.communityNewsfeedDetailLike,
|
|
|
|
+ onLike: () {
|
|
|
|
+ Log.d('点击了like button');
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ const SizedBox(width: 10,),
|
|
|
|
+
|
|
|
|
+ MyTextView(
|
|
|
|
+ "Like",
|
|
|
|
+ textColor: context.appColors.whiteBG,
|
|
|
|
+ fontSize: 14,
|
|
|
|
+ isFontRegular: true,
|
|
|
|
+ )
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ).onTap((){
|
|
|
|
+ final state = _likeButtonKey.currentState;
|
|
|
|
+ state?.triggerTap();
|
|
|
|
+ })
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ Expanded(
|
|
|
|
+ child: Row(
|
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
|
+ children: [
|
|
|
|
+ Container(
|
|
|
|
+ alignment: Alignment.center,
|
|
|
|
+ padding: const EdgeInsets.only(left: 10,right: 10),
|
|
|
|
+ child: Wrap(
|
|
|
|
+ children: [
|
|
|
|
+ MyLoadImage(
|
|
|
|
+ Assets.communityNewsfeedDetailComment,
|
|
|
|
+ width: 17.5,
|
|
|
|
+ height: 16.5,
|
|
|
|
+ ),
|
|
|
|
+ const SizedBox(width: 10,),
|
|
|
|
+ MyTextView(
|
|
|
|
+ "Comment",
|
|
|
|
+ textColor: context.appColors.whiteBG,
|
|
|
|
+ fontSize: 14,
|
|
|
|
+ isFontRegular: true,
|
|
|
|
+ ),
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ).onTap((){
|
|
|
|
+ vm.handlerCommentClick(context);
|
|
|
|
+ })
|
|
|
|
+ ],
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ ]
|
|
|
|
+ )
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
+ }
|
|
}
|
|
}
|