Merge branch 'laiiihz'

* laiiihz:
  update user profile avatar's placeholder
  deprecated activityDetailPage
  添加话题详情页面
  话题点赞功能接口对接
  修复话题列表的显示问题
  更新动态卡片
  社区动态页面添加新增按钮
  添加社区新的动态页面
  chat card 添加多图片显示
  添加删除动态弹框
  update chat card. working on chat detail page.
hmxc
小赖 4 years ago
commit 949f05eba5

@ -170,9 +170,20 @@ class _Community {
String get boardDetail => '/user/announcement/findById';
///
String get topicList => '/user/gambit/list';
String get topicList => '/user/gambit/listGambit';
String get eventByTopicId => '/user/gambit/listByGambitId';
String get newEventList => '/user/gambit/list';
///
String get addEvent => '/user/gambit/writePost';
///app/
String get like => '/user/gambit/likes';
///4
String get hotTopic => '/user/gambit/findActivityGambit';
}
class _Upload {
@ -184,4 +195,6 @@ class _Upload {
///
String get uploadRepair => '/user/upload/uploadRepair';
String get uploadEvent => '/user/upload/uploadGambit';
}

@ -2,153 +2,52 @@ import 'package:akuCommunity/model/common/img_model.dart';
class CommunityTopicModel {
int id;
int createId;
int isComment;
int isLike;
String createName;
String title;
String summary;
String content;
String gambitTitle;
String createDate;
List<LikeNames> likeNames;
List<ImgModel> imgUrls;
List<ImgModel> headSculptureImgUrl;
List<GambitThemeCommentVoList> gambitThemeCommentVoList;
List<ImgModel> imgUrl;
int activityNum;
String get firstImg {
var firstImg = '';
if (imgUrls?.isNotEmpty ?? false) {
firstImg = imgUrls?.first?.url ?? '';
}
return firstImg;
if (imgUrl.isEmpty)
return '';
else
return imgUrl.first.url;
}
CommunityTopicModel(
{this.id,
this.createId,
this.isComment,
this.isLike,
this.createName,
this.title,
this.summary,
this.content,
this.gambitTitle,
this.createDate,
this.likeNames,
this.imgUrls,
this.headSculptureImgUrl,
this.gambitThemeCommentVoList});
this.imgUrl,
this.activityNum});
CommunityTopicModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
createId = json['createId'];
isComment = json['isComment'];
isLike = json['isLike'];
createName = json['createName'];
title = json['title'];
summary = json['summary'];
content = json['content'];
gambitTitle = json['gambitTitle'];
createDate = json['createDate'];
if (json['likeNames'] != null) {
likeNames = new List<LikeNames>();
json['likeNames'].forEach((v) {
likeNames.add(new LikeNames.fromJson(v));
});
}
if (json['imgUrls'] != null) {
imgUrls = new List<ImgModel>();
json['imgUrls'].forEach((v) {
imgUrls.add(new ImgModel.fromJson(v));
if (json['imgUrl'] != null) {
imgUrl = new List<ImgModel>();
json['imgUrl'].forEach((v) {
imgUrl.add(new ImgModel.fromJson(v));
});
} else
imgUrls = [];
if (json['headSculptureImgUrl'] != null) {
headSculptureImgUrl = new List<ImgModel>();
json['headSculptureImgUrl'].forEach((v) {
headSculptureImgUrl.add(new ImgModel.fromJson(v));
});
} else
headSculptureImgUrl = [];
if (json['gambitThemeCommentVoList'] != null) {
gambitThemeCommentVoList = new List<GambitThemeCommentVoList>();
json['gambitThemeCommentVoList'].forEach((v) {
gambitThemeCommentVoList.add(new GambitThemeCommentVoList.fromJson(v));
});
}
imgUrl = [];
activityNum = json['activityNum'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['createId'] = this.createId;
data['isComment'] = this.isComment;
data['isLike'] = this.isLike;
data['createName'] = this.createName;
data['title'] = this.title;
data['summary'] = this.summary;
data['content'] = this.content;
data['gambitTitle'] = this.gambitTitle;
data['createDate'] = this.createDate;
if (this.likeNames != null) {
data['likeNames'] = this.likeNames.map((v) => v.toJson()).toList();
}
if (this.imgUrls != null) {
data['imgUrls'] = this.imgUrls.map((v) => v.toJson()).toList();
}
if (this.headSculptureImgUrl != null) {
data['headSculptureImgUrl'] =
this.headSculptureImgUrl.map((v) => v.toJson()).toList();
if (this.imgUrl != null) {
data['imgUrl'] = this.imgUrl.map((v) => v.toJson()).toList();
}
if (this.gambitThemeCommentVoList != null) {
data['gambitThemeCommentVoList'] =
this.gambitThemeCommentVoList.map((v) => v.toJson()).toList();
}
return data;
}
}
class LikeNames {
int id;
String name;
LikeNames({this.id, this.name});
LikeNames.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
return data;
}
}
class GambitThemeCommentVoList {
int id;
String parentName;
String content;
String createName;
String createDate;
GambitThemeCommentVoList(
{this.id,
this.parentName,
this.content,
this.createName,
this.createDate});
GambitThemeCommentVoList.fromJson(Map<String, dynamic> json) {
id = json['id'];
parentName = json['parentName'];
content = json['content'];
createName = json['createName'];
createDate = json['createDate'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['parentName'] = this.parentName;
data['content'] = this.content;
data['createName'] = this.createName;
data['createDate'] = this.createDate;
data['activityNum'] = this.activityNum;
return data;
}
}

@ -17,6 +17,8 @@ import 'package:akuCommunity/widget/bee_scaffold.dart';
import 'package:akuCommunity/widget/bottom_button.dart';
import 'package:akuCommunity/widget/cached_image_wrapper.dart';
//TODO CLEAN BOTTOM CODES.
@Deprecated("sh*t activities_details_page need to be cleaned.")
class ActivitiesDetailsPage extends StatefulWidget {
final Bundle bundle;
ActivitiesDetailsPage({Key key, this.bundle}) : super(key: key);

@ -124,8 +124,7 @@ class _PersonalIndexState extends State<PersonalIndex>
tag: 'AVATAR',
child: ClipOval(
child: FadeInImage.assetNetwork(
//TODO PLACEHOLDER
placeholder: R.ASSETS_ICONS_PROPOSAL_PNG,
placeholder: R.ASSETS_IMAGES_PLACEHOLDER_WEBP,
image: API.image(
userProvider?.userInfoModel?.imgUrl ?? ''),
height: 106.w,

@ -98,7 +98,7 @@ class _UserProfilePageState extends State<UserProfilePage> {
tag: 'AVATAR',
child: ClipOval(
child: FadeInImage.assetNetwork(
placeholder: R.ASSETS_ICONS_PROPOSAL_PNG,
placeholder: R.ASSETS_IMAGES_PLACEHOLDER_WEBP,
image: API.image(userProvider.userInfoModel.imgUrl),
height: 56.w,
width: 56.w,

@ -0,0 +1,148 @@
import 'dart:io';
import 'package:akuCommunity/base/base_style.dart';
import 'package:akuCommunity/constants/api.dart';
import 'package:akuCommunity/utils/headers.dart';
import 'package:akuCommunity/utils/network/base_model.dart';
import 'package:akuCommunity/utils/network/net_util.dart';
import 'package:akuCommunity/widget/picker/grid_image_picker.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:velocity_x/velocity_x.dart';
class AddNewEventPage extends StatefulWidget {
AddNewEventPage({Key key}) : super(key: key);
@override
_AddNewEventPageState createState() => _AddNewEventPageState();
}
class _AddNewEventPageState extends State<AddNewEventPage> {
bool _commentable = true;
List<File> _files = [];
TextEditingController _textEditingController = TextEditingController();
///
_addEvent() async {
VoidCallback cancel = BotToast.showLoading();
final String content = _textEditingController.text;
List<String> imgs;
if (_files.isNotEmpty) {
imgs = await NetUtil().uploadFiles(_files, API.upload.uploadEvent);
}
Map<String, dynamic> params = {
//TODO ID
'gambitId': -1,
'content': content,
'isComment': _commentable ? 1 : 0,
'isPublic': 1,
'imgUrls': imgs,
};
BaseModel baseModel = await NetUtil().post(
API.community.addEvent,
params: params,
showMessage: true,
);
cancel();
if (baseModel.status) {
Get.back(result: true);
}
}
_buildSelectable() {
return MaterialButton(
onPressed: () {
setState(() {
_commentable = !_commentable;
});
},
height: 96.w,
child: Row(
children: [
Icon(
CupertinoIcons.bubble_left,
size: 32.w,
),
8.wb,
'不可评论'.text.size(28.sp).make(),
Spacer(),
AnimatedOpacity(
opacity: _commentable ? 0 : 1,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOutCubic,
child: Icon(
Icons.check_rounded,
color: Colors.black,
size: 40.w,
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: MaterialButton(
padding: EdgeInsets.zero,
onPressed: Get.back,
child: '取消'.text.size(34.sp).make(),
),
leadingWidth: 108.w,
centerTitle: true,
title: '社区'.text.make(),
actions: [
Hero(
tag: 'event_add',
child: MaterialButton(
elevation: 0,
minWidth: 116.w,
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4.w),
),
color: kPrimaryColor,
onPressed: _addEvent,
child: '发表'.text.size(34.sp).make(),
).centered(),
),
32.wb,
],
),
body: ListView(
padding: EdgeInsets.symmetric(horizontal: 64.w, vertical: 32.w),
children: [
TextField(
minLines: 3,
maxLines: 99,
controller: _textEditingController,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
hintText: '这一刻的想法',
hintStyle: TextStyle(
color: Color(0xFF999999),
fontSize: 34.sp,
),
),
),
GridImagePicker(onChange: (files) => _files = files),
100.hb,
Divider(height: 1.w),
_buildSelectable(),
Divider(height: 1.w),
28.hb,
//TODO
],
).material(color: Colors.white),
);
}
}

@ -1,3 +1,4 @@
import 'package:akuCommunity/ui/community/community_views/add_new_event_page.dart';
import 'package:akuCommunity/ui/community/community_views/my_community_view.dart';
import 'package:akuCommunity/ui/community/community_views/new_community_view.dart';
import 'package:akuCommunity/ui/community/community_views/topic/topic_community_view.dart';
@ -6,6 +7,7 @@ import 'package:akuCommunity/widget/bee_scaffold.dart';
import 'package:akuCommunity/widget/buttons/column_action_button.dart';
import 'package:akuCommunity/widget/tab_bar/bee_tab_bar.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class CommunityPage extends StatefulWidget {
CommunityPage({Key key}) : super(key: key);
@ -39,6 +41,11 @@ class _CommunityPageState extends State<CommunityPage>
path: R.ASSETS_ICONS_ALARM_PNG,
),
],
fab: FloatingActionButton(
onPressed: () => Get.to(AddNewEventPage()),
heroTag: 'event_add',
child: Icon(Icons.add),
),
appBarBottom: PreferredSize(
preferredSize: Size.fromHeight(48),
child: Align(

@ -0,0 +1,18 @@
import 'package:akuCommunity/widget/bee_scaffold.dart';
import 'package:flutter/material.dart';
class EventDetailPage extends StatefulWidget {
EventDetailPage({Key key}) : super(key: key);
@override
_EventDetailPageState createState() => _EventDetailPageState();
}
class _EventDetailPageState extends State<EventDetailPage> {
@override
Widget build(BuildContext context) {
return BeeScaffold(
title: '详情',
);
}
}

@ -1,4 +1,9 @@
import 'package:akuCommunity/constants/api.dart';
import 'package:akuCommunity/model/community/event_item_model.dart';
import 'package:akuCommunity/pages/things_page/widget/bee_list_view.dart';
import 'package:akuCommunity/ui/community/community_views/widgets/chat_card.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
class NewCommunityView extends StatefulWidget {
NewCommunityView({Key key}) : super(key: key);
@ -9,10 +14,42 @@ class NewCommunityView extends StatefulWidget {
class _NewCommunityViewState extends State<NewCommunityView>
with AutomaticKeepAliveClientMixin {
EasyRefreshController _refreshController = EasyRefreshController();
@override
void dispose() {
_refreshController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
return Container();
return BeeListView(
path: API.community.newEventList,
controller: _refreshController,
convert: (model) {
return model.tableList.map((e) => EventItemModel.fromJson(e)).toList();
},
builder: (items) {
return ListView.builder(
itemBuilder: (context, index) {
final item = items[index] as EventItemModel;
return ChatCard(
content: item.content,
name: item.createName ?? '',
topic: item.gambitTitle ?? '',
contentImg: item.imgUrls,
date: item.date,
id: item.createId,
headImg: item.headSculptureImgUrl,
themeId: item.id,
initLike: item.isLike == 1,
);
},
itemCount: items.length,
);
},
);
}
@override

@ -56,9 +56,7 @@ class _TopicCommunityViewState extends State<TopicCommunityView>
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
//TODO
// model.summary
child: ('#${''}')
child: ('#${model.summary}')
.text
.center
.size(28.sp)
@ -76,7 +74,7 @@ class _TopicCommunityViewState extends State<TopicCommunityView>
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(model?.gambitTitle ?? '')
(model?.title ?? '')
.text
.maxLines(2)
.size(28.sp)

@ -4,7 +4,6 @@ import 'package:akuCommunity/model/community/event_item_model.dart';
import 'package:akuCommunity/pages/things_page/widget/bee_list_view.dart';
import 'package:akuCommunity/ui/community/community_views/topic/topic_sliver_header.dart';
import 'package:akuCommunity/ui/community/community_views/widgets/chat_card.dart';
import 'package:akuCommunity/utils/headers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
@ -28,6 +27,11 @@ class _TopicDetailPageState extends State<TopicDetailPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
heroTag: 'event_add',
onPressed: () {},
child: Icon(Icons.add),
),
body: BeeListView(
convert: (model) {
return model.tableList
@ -55,11 +59,15 @@ class _TopicDetailPageState extends State<TopicDetailPage> {
(context, index) {
final item = items[index] as EventItemModel;
return ChatCard(
initLike: item.isLike == 1,
themeId: item.id,
content: item.content,
name: item.createName,
title: item.gambitTitle,
topic: item.gambitTitle,
headImg: item.headSculptureImgUrl,
contentImg: item.imgUrls,
date: item.date,
id: item.createId,
);
},
childCount: items.length,

@ -1,25 +1,44 @@
import 'package:akuCommunity/constants/api.dart';
import 'package:akuCommunity/model/common/img_model.dart';
import 'package:akuCommunity/provider/user_provider.dart';
import 'package:akuCommunity/ui/community/community_views/event_detail_page.dart';
import 'package:akuCommunity/utils/bee_date_util.dart';
import 'package:akuCommunity/utils/headers.dart';
import 'package:akuCommunity/utils/network/net_util.dart';
import 'package:akuCommunity/widget/picker/bee_image_preview.dart';
import 'package:akuCommunity/widget/views/bee_grid_image_view.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:provider/provider.dart';
import 'package:velocity_x/velocity_x.dart';
class ChatCard extends StatefulWidget {
final String name;
final String title;
final String topic;
final List<ImgModel> headImg;
final List<ImgModel> contentImg;
final DateTime date;
final bool canDelete;
final bool initLike;
final String content;
///userID
final int id;
final int themeId;
ChatCard({
Key key,
this.name,
this.title,
this.headImg,
this.contentImg,
@required this.name,
@required this.topic,
@required this.headImg,
@required this.contentImg,
@required this.date,
this.canDelete,
this.initLike = false,
@required this.id,
@required this.content,
@required this.themeId,
}) : super(key: key);
@override
@ -27,6 +46,13 @@ class ChatCard extends StatefulWidget {
}
class _ChatCardState extends State<ChatCard> {
bool _like = false;
bool get _isMyself {
final userProvider = Provider.of<UserProvider>(context, listen: false);
return (userProvider?.userInfoModel?.id ?? -1) == widget.id;
}
String get firstHead {
if (widget.headImg == null || widget.headImg.isEmpty)
return '';
@ -37,20 +63,146 @@ class _ChatCardState extends State<ChatCard> {
_renderImage() {
if (widget.contentImg.isEmpty) return SizedBox();
if (widget.contentImg.length == 1)
return ConstrainedBox(
return MaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
padding: EdgeInsets.zero,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.w),
),
onPressed: () {
Get.to(
BeeImagePreview.path(path: widget.contentImg.first.url),
opaque: false,
);
},
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 300.w,
minWidth: 300.w,
maxWidth: 300.w,
),
child: Hero(
tag: widget.contentImg.first.url,
child: FadeInImage.assetNetwork(
placeholder: R.ASSETS_IMAGES_PLACEHOLDER_WEBP,
image: API.image(widget.contentImg.first.url),
),
),
),
);
else
return BeeGridImageView(
urls: widget.contentImg.map((e) => e.url).toList());
}
_buildMoreButton() {
return Builder(builder: (context) {
return MaterialButton(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6.w),
),
padding: EdgeInsets.zero,
height: 40.w,
minWidth: 0,
color: Color(0xFFD8D8D8),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
onPressed: () {
BotToast.showAttachedWidget(
targetContext: context,
preferDirection: PreferDirection.leftCenter,
attachedBuilder: (cancel) {
return Padding(
padding: EdgeInsets.only(right: 10.w),
child: Material(
color: Color(0xFFD8D8D8),
borderRadius: BorderRadius.circular(8.w),
clipBehavior: Clip.antiAlias,
child: SizedBox(
height: 78.w,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
MaterialButton(
height: 78.w,
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
onPressed: () async {
cancel();
await NetUtil().get(
API.community.like,
params: {'themeId': widget.id},
showMessage: true,
);
setState(() {
_like = !_like;
});
},
child: [
_like
? Icon(Icons.favorite,
size: 30.w, color: Colors.red)
: Icon(Icons.favorite_border, size: 30.w),
10.wb,
''.text.make(),
].row(),
),
VerticalDivider(width: 1.w, thickness: 1.w),
MaterialButton(
height: 78.w,
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
onPressed: () {},
child: [
Icon(CupertinoIcons.bubble_right, size: 30.w),
10.wb,
'评论'.text.make(),
].row(),
),
],
),
),
),
);
},
);
},
child: Row(
children: [
20.wb,
Container(
height: 8.w,
width: 8.w,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4.w),
),
),
8.wb,
Container(
height: 8.w,
width: 8.w,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4.w),
),
),
20.wb,
],
),
);
});
}
@override
void initState() {
super.initState();
_like = widget.initLike ?? false;
}
@override
Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context);
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.white,
@ -60,12 +212,18 @@ class _ChatCardState extends State<ChatCard> {
),
),
),
child: MaterialButton(
padding: EdgeInsets.zero,
onPressed: () {
Get.to(EventDetailPage());
},
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Material(
color: Color(0xFFF5F5F5),
borderRadius: BorderRadius.circular(6.w),
clipBehavior: Clip.antiAlias,
child: FadeInImage.assetNetwork(
placeholder: R.ASSETS_IMAGES_PLACEHOLDER_WEBP,
image: API.image(firstHead),
@ -79,19 +237,70 @@ class _ChatCardState extends State<ChatCard> {
children: [
widget.name.text.size(36.sp).make(),
6.hb,
widget.title.text.make(),
widget.content.text.make(),
20.hb,
_renderImage(),
widget.topic.isEmpty
? SizedBox()
: Chip(
label: '#${widget.topic}'.text.size(22.sp).make(),
padding: EdgeInsets.symmetric(
horizontal: 16.w, vertical: 5.w),
labelPadding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
shape: StadiumBorder(
side: BorderSide(),
),
),
Row(
children: [
BeeDateUtil(widget.date).timeAgo.text.make(),
BeeDateUtil(widget.date)
.timeAgo
.text
.size(28.sp)
.color(Color(0xFF999999))
.make(),
_isMyself
? FlatButton(
materialTapTargetSize:
MaterialTapTargetSize.shrinkWrap,
height: 48.w,
onPressed: () async {
bool result =
await Get.dialog(CupertinoAlertDialog(
title: '你确定删除吗'.text.isIntrinsic.make(),
actions: [
CupertinoDialogAction(
child: '取消'.text.black.isIntrinsic.make(),
onPressed: () => Get.back(),
),
CupertinoDialogAction(
child: '确定'
.text
.color(Colors.orange)
.isIntrinsic
.make(),
onPressed: () => Get.back(result: true),
),
],
));
if (result == true) {
//TODO delete operation
}
},
child: '删除'.text.black.size(28.sp).make(),
)
: SizedBox(),
Spacer(),
_buildMoreButton(),
],
),
],
).expand(),
],
).p(20.w),
),
);
}
}

@ -12,6 +12,7 @@ import 'package:velocity_x/velocity_x.dart';
// Project imports:
import 'package:akuCommunity/utils/headers.dart';
//TODO
class BeeImagePicker {
static Future<File> pick({
String title,

@ -50,16 +50,13 @@ class _BeeImagePreviewState extends State<BeeImagePreview> {
onTap: Get.back,
child: Scaffold(
backgroundColor: Colors.black54,
body: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: InteractiveViewer(
body: InteractiveViewer(
boundaryMargin: EdgeInsets.all(48),
minScale: 0.2,
maxScale: 10,
child: Center(child: image),
),
),
),
);
}
}

Loading…
Cancel
Save