AI_Drawing/lib/tools/gallery/gallery_content_page.dart
2024-06-03 15:30:15 +08:00

698 lines
25 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'package:aiplot/tools/gallery/gallery_content_model.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import '../../bean/gallery_label_bean.dart';
import '../../bean/gallery_work_label_bean.dart';
import '../../bean/gallery_work_list_bean.dart';
import '../../bean/recommender_bean.dart';
import '../../common/Global.dart';
import '../../common/dialog_bean.dart';
import '../../common/dialog_manager.dart';
import '../../common/dialog_util.dart';
import '../../common/func.dart';
import '../../dialog/login_dialog.dart';
import '../../dialog/phone_login_dialog.dart';
import '../../generated/l10n.dart';
import '../../network/NetworkConfig.dart';
import '../drawdetails/expert_user_details_page.dart';
import '../drawdetails/influential_details_page.dart';
class GalleryContentPage extends StatefulWidget {
GalleryContentPage({Key? key}) : super(key: key);
@override
State<GalleryContentPage> createState() => _GalleryContentPageState();
}
class _GalleryContentPageState extends State<GalleryContentPage> with SingleTickerProviderStateMixin {
StreamSubscription? subscription;
final GalleryContentModel _viewModel = GalleryContentModel();
GlobalKey<LoginDialogState> loginDialogKey = GlobalKey(); //登录弹框key
final ScrollController _scrollController = ScrollController();
TabController? tabController;
List<GalleryLabelBean> labelList = [];
List<Tab> myTabs = [];
String influentialCode = "";
List<RecommenderBean> recommenderList = [];
List<GalleryWorkLabelBean> workLabelList = [];
int currentLabelIndex = 0; //当前选中标签
int currentChild = 1; //当前选中的子标签
List<GalleryWorkListBean> galleryList = [];
int index = 1; //当前页数
FocusNode focusNode = FocusNode();
//创建StreamController
StreamController? streamController;
// 获取StreamSink用于发射事件
StreamSink? get streamSink => streamController?.sink;
// 获取Stream用于监听
Stream? get streamData => streamController?.stream;
void influentialChange(String str) {
influentialCode = str.toUpperCase();
}
void getWorksListByLabel(bool isLoad) {
EasyLoading.show(status: 'loading...');
_viewModel.getWorksListByLabel(workLabelList[currentLabelIndex].LabelId, currentChild, index, isLoad);
}
@override
void initState() {
// TODO: implement initState
super.initState();
streamController = StreamController<bool>();
//网络请求回调
subscription = _viewModel.streamController.stream.listen((newData) {
String code = newData['code'];
if (code.isNotEmpty) {
EasyLoading.dismiss();
switch (code) {
case "getRecommenderList":
recommenderList = newData['data'];
break;
case "getGalleryWorkLabel":
workLabelList = newData['data'];
getWorksListByLabel(false);
break;
case "getWorksListByLabel":
if (newData['isLoad']) {
galleryList.addAll(newData['data']);
} else {
galleryList = newData['data'];
}
break;
case "getUserHomePageByPw": //搜索达人
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ExpertUserDetailsPage(
workUserId: "${newData['data']}",
worksID: '0',
),
));
break;
default:
String message = newData['data'];
EasyLoading.showToast(message);
break;
}
setState(() {});
}
});
//上拉加载
_scrollController.addListener(() {
//判断是否滑动到了页面的最底部
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
//如果不是最后一页数据则生成新的数据添加到list里面
index++;
getWorksListByLabel(true);
}
///置顶按钮
if (_scrollController.position.pixels > 600) {
streamSink?.add(true);
} else {
streamSink?.add(false);
}
});
_viewModel.getRecommenderList();
_viewModel.getGalleryWorkLabel();
}
@override
void dispose() {
// TODO: implement dispose
subscription?.cancel();
streamController?.close();
tabController?.dispose();
focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
margin: const EdgeInsets.only(right: 10),
child: const Image(
width: 23,
height: 23,
image: AssetImage('assets/images/ic_title.png'),
),
),
Text(
"AI${S.of(context).Gallery}",
style: const TextStyle(color: Colors.black, fontSize: 20),
),
],
),
centerTitle: true,
),
body: RefreshIndicator(
onRefresh: _onRefresh,
child: Stack(
children: [
SingleChildScrollView(
controller: _scrollController,
child: Container(
margin: const EdgeInsets.only(left: 15),
child: Column(
children: [
///搜索达人
Container(
margin: const EdgeInsets.only(right: 15),
child: Container(
width: double.infinity,
height: 40,
decoration: BoxDecoration(
border: Border.all(width: 1, color: const Color(0xFF8841FF)),
borderRadius: const BorderRadius.all(Radius.circular(20)),
),
child: Stack(
alignment: Alignment.center,
children: [
const Positioned(
left: 17,
child: Image(
image: AssetImage('assets/images/ic_search.png'),
width: 19,
height: 19,
)),
Positioned(
left: 47,
right: 70,
child: Container(
height: 30,
width: double.infinity,
alignment: Alignment.centerLeft,
child: TextField(
keyboardType: TextInputType.text,
focusNode: focusNode,
decoration: InputDecoration(
hintText: S.of(context).Search_influential,
hintStyle: const TextStyle(fontSize: 14, color: Color(0xFF999999)),
border: InputBorder.none,
isCollapsed: true,
),
onChanged: influentialChange,
),
),
),
Positioned(
right: 7,
child: GestureDetector(
onTap: () {
if (NetworkConfig.userId == "") {
showLoginDialog();
} else {
if (influentialCode != "") {
focusNode.unfocus();
_viewModel.getUserHomePageByPw(influentialCode);
}
}
},
child: Container(
width: 60,
height: 28,
alignment: Alignment.center,
decoration: BoxDecoration(color: const Color(0xFF8841FF), borderRadius: BorderRadius.circular(14)),
child: Text(
S.of(context).search,
style: const TextStyle(color: Colors.white, fontSize: 14),
),
),
)),
],
),
),
),
///推荐达人
recommenderList.isNotEmpty
? Container(
alignment: Alignment.centerLeft,
margin: const EdgeInsets.only(top: 20),
child: Text(
S.of(context).Recommended_influencers,
style: const TextStyle(fontSize: 16, color: Colors.black, fontWeight: FontWeight.w600),
),
)
: Container(),
recommenderList.isNotEmpty
? Container(
height: 70,
alignment: Alignment.centerLeft,
margin: const EdgeInsets.only(top: 20, right: 15),
child: ListView.builder(
shrinkWrap: true,
itemCount: recommenderList.length,
itemBuilder: (context, index) {
return influential(recommenderList[index]);
},
scrollDirection: Axis.horizontal),
)
: Container(),
///作品展示
Container(
alignment: Alignment.centerLeft,
margin: const EdgeInsets.only(top: 20),
child: Text(
S.of(context).Exhibition_works,
style: const TextStyle(fontSize: 16, color: Colors.black, fontWeight: FontWeight.w600),
),
),
///标签
Container(
height: 25,
alignment: Alignment.center,
margin: const EdgeInsets.only(top: 12),
child: ListView.builder(
itemCount: workLabelList.length,
itemBuilder: (context, index) {
return _labelItem(workLabelList[index], index);
},
scrollDirection: Axis.horizontal,
),
),
///子标签
Container(
margin: const EdgeInsets.only(top: 11),
child: Row(
children: [
GestureDetector(
onTap: () {
currentChild = 1;
getWorksListByLabel(false);
},
child: Container(
margin: const EdgeInsets.only(right: 10),
child: Text(
S.of(context).Newest,
style: TextStyle(color: currentChild == 1 ? Colors.black : Color(0xFF999999)),
),
),
),
GestureDetector(
onTap: () {
currentChild = 2;
getWorksListByLabel(false);
},
child: Container(
margin: EdgeInsets.only(right: 10),
child: Text(
S.of(context).Popular,
style: TextStyle(color: currentChild == 2 ? Colors.black : Color(0xFF999999)),
),
),
),
GestureDetector(
onTap: () {
currentChild = 3;
getWorksListByLabel(false);
},
child: Container(
margin: EdgeInsets.only(right: 10),
child: Text(
S.of(context).all,
style: TextStyle(color: currentChild == 3 ? Colors.black : Color(0xFF999999)),
),
),
),
],
),
),
Container(
margin: EdgeInsets.only(top: 16, right: 15),
child: MasonryGridView.count(
crossAxisCount: 2,
itemCount: galleryList.length,
itemBuilder: (BuildContext context, int index) {
return _galleryItem(galleryList[index], index);
},
shrinkWrap: true,
// 纵向元素间距
mainAxisSpacing: 0,
// 横向元素间距
crossAxisSpacing: 10,
physics: const NeverScrollableScrollPhysics(),
),
),
],
),
),
),
///置顶
StreamBuilder(
stream: streamData,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data != null && snapshot.data) {
return Positioned(
right: 10,
bottom: 50,
child: GestureDetector(
onTap: () {
_scrollController.animateTo(0, duration: Duration(milliseconds: 500), curve: Curves.decelerate);
},
child: const Image(
width: 60,
image: AssetImage('assets/images/ic_topping.png'),
),
),
);
} else {
return Container();
}
}),
],
),
),
);
}
// 下拉刷新
Future<void> _onRefresh() async {
// 持续两秒
await Future.delayed(const Duration(milliseconds: 1500), () {
currentLabelIndex = 0;
currentChild = 1;
index = 1;
galleryList = [];
_viewModel.getRecommenderList();
_viewModel.getGalleryWorkLabel();
});
}
//达人条目
influential(RecommenderBean data) {
return GestureDetector(
onTap: () {
if (NetworkConfig.userId == "") {
showLoginDialog();
} else {
focusNode.unfocus();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ExpertUserDetailsPage(
workUserId: "${data.UserId}",
worksID: '${data.UserFollow}',
),
));
}
},
child: Container(
width: 50,
margin: EdgeInsets.only(right: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ClipOval(
child: CachedNetworkImage(
width: 50,
height: 50,
imageUrl: data.UserIconUrl!,
errorWidget: (context, url, error) => Icon(Icons.error),
),
),
SizedBox(
width: 50,
child: Text(
"${data.NickName}",
style: TextStyle(fontSize: 12, color: Color(0xFF999999)),
overflow: TextOverflow.ellipsis,
),
)
],
),
));
}
//作品标签
_labelItem(GalleryWorkLabelBean data, index) {
return GestureDetector(
onTap: () {
if (NetworkConfig.userId == "") {
showLoginDialog();
} else {
focusNode.unfocus();
currentLabelIndex = index;
currentChild = 1;
getWorksListByLabel(false);
setState(() {});
}
},
child: Container(
padding: const EdgeInsets.only(left: 10, right: 10),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(currentLabelIndex == index ? 0xFF8841FF : 0xFFF6F7FF),
borderRadius: const BorderRadius.all(Radius.circular(20)),
),
margin: const EdgeInsets.only(right: 12),
child: Text(
"${data.LabelName}",
style: TextStyle(color: currentLabelIndex == index ? Colors.white : Color(0xFF999999), fontSize: 13),
),
),
);
}
//画廊
_galleryItem(GalleryWorkListBean bean, int index) {
return Column(
children: [
///Ai图
ClipRRect(
borderRadius: BorderRadius.circular(7),
child: GestureDetector(
onTap: () {
focusNode.unfocus();
if (NetworkConfig.userId == "") {
showLoginDialog();
} else {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => DrawDetailsPage(
// false,
// drawId: bean.DrawId.toString(),
// isMyWork: false,
// status: 3,
// ),
// ));
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => InfluentialDetailsPage(bean.DrawId.toString()),
));
}
},
child: Stack(
children: [
CachedNetworkImage(
imageUrl: bean.ImageUrl!,
errorWidget: (context, url, error) => Icon(Icons.error),
),
bean.IsTalent == 1
? const Positioned(
left: 6,
top: 6,
child: Image(
width: 42,
image: AssetImage('assets/images/ic_portfolio.webp'),
))
: Container(),
],
),
),
),
Row(
children: [
bean.IsTalent == 1
? Container(
width: 48,
height: 15,
alignment: Alignment.center,
margin: EdgeInsets.only(top: 2),
decoration: BoxDecoration(
border: Border.all(color: Color(0xFFFF6316), width: 1),
borderRadius: BorderRadius.all(Radius.circular(3)),
),
child: Text(
S.of(context).Expert_selection,
style: TextStyle(fontSize: 10, color: Color(0xFFFF661B)),
),
)
: Container(),
Container(
width: bean.IsTalent == 1 ? 100 : 140,
alignment: Alignment.centerLeft,
margin: EdgeInsets.only(left: 5),
child: Text(
"${bean.Title}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.black),
),
),
],
),
Container(
height: 25,
margin: EdgeInsets.only(bottom: 10),
child: Stack(
alignment: Alignment.center,
children: [
///头像
Positioned(
left: 0,
child: ClipOval(
child: CachedNetworkImage(
fit: BoxFit.fitHeight,
width: 18,
height: 18,
imageUrl: bean.UserIocn!,
errorWidget: (context, url, error) => Image(
fit: BoxFit.fitWidth,
width: 18,
height: 18,
image: AssetImage('assets/images/head.png'),
),
),
),
),
Positioned(
left: 23,
child: Container(
width: 80,
child: Text(
bean.UserNickName!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.black, fontSize: 12),
),
),
),
///点赞收藏
Positioned(
right: 0,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
focusNode.unfocus();
if (NetworkConfig.userId == "") {
showLoginDialog();
} else {
if (NetworkConfig.userId != "${bean.UserId}") {
bean.IsCollect = !bean.IsCollect!;
if (bean.IsCollect!) {
bean.LikeNum = (bean.LikeNum! + 1);
} else {
if (bean.LikeNum! > 0) {
bean.LikeNum = (bean.LikeNum! - 1);
}
}
setState(() {});
}
_viewModel.userDrawCollect(bean.IsCollect!, bean.DrawId.toString());
}
},
child: Container(
padding: EdgeInsets.all(15),
child: Row(
children: [
Image(
width: 13,
height: 12,
image: bean.IsCollect!
? const AssetImage('assets/images/ic_collect_s.png')
: const AssetImage('assets/images/ic_collect.png'),
),
Container(
margin: EdgeInsets.only(left: 5),
child: Text(
bean.LikeNum.toString(),
style: TextStyle(color: bean.IsCollect! ? Color(0xFFBB72E0) : Colors.black, fontSize: 12),
),
)
],
),
)),
),
],
),
),
],
);
}
//弹出登录
showLoginDialog() {
DialogManager()
..add(DialogBean(
dialogPriority: DialogPriority.highClear,
createDialogWidget: () => DialogUtil.createTipWidget(
context,
LoginDialog(
loginDialogKey,
onTap: (index) {
switch (index) {
case 0:
if (loginDialogKey.currentState != null) {
loginDialogKey.currentState!.Pop();
}
FunctionUtil.bottomSheetDialog(context, PhoneLoginDialog());
break;
case 1: //谷歌登录
Map<String, String> map = {"googleLogin": "googleLogin"};
invokeNativeMethod("googleLogin", map);
break;
}
},
),
"LoginDialog",
canceled: true)))
..show(context);
}
// 获取原生的值
invokeNativeMethod(String method, Map<String, dynamic> map) async {
dynamic args;
try {
args = await Global.method.invokeMethod(method, map);
} on PlatformException catch (e) {}
}
}