|
|
@@ -0,0 +1,554 @@ |
|
|
|
import 'dart:async'; |
|
|
|
import 'dart:convert'; |
|
|
|
import 'dart:io'; |
|
|
|
import 'dart:typed_data'; |
|
|
|
import 'dart:ui'; |
|
|
|
import 'dart:ui' as ui; |
|
|
|
|
|
|
|
import 'package:cached_network_image/cached_network_image.dart'; |
|
|
|
import 'package:flutter/cupertino.dart'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:flutter/rendering.dart'; |
|
|
|
import 'package:flutter/services.dart'; |
|
|
|
import 'package:flutter_swiper/flutter_swiper.dart'; |
|
|
|
import 'package:fluttertoast/fluttertoast.dart'; |
|
|
|
import 'package:path_provider/path_provider.dart'; |
|
|
|
import 'package:permission_handler/permission_handler.dart'; |
|
|
|
import 'package:share_extend/share_extend.dart'; |
|
|
|
import 'package:sharesdk_plugin/sharesdk_plugin.dart'; |
|
|
|
import 'package:zhiying_base_widget/dialog/loading/loading.dart'; |
|
|
|
import 'package:zhiying_base_widget/utils/image_download_util/image_download_util.dart'; |
|
|
|
import 'package:zhiying_base_widget/widgets/share/models/share_alert_model.dart'; |
|
|
|
import 'package:zhiying_base_widget/widgets/share/models/share_data_model.dart'; |
|
|
|
import 'package:zhiying_base_widget/widgets/share/models/share_icon_model.dart'; |
|
|
|
import 'package:zhiying_base_widget/widgets/share/share_alert_content.dart'; |
|
|
|
import 'package:zhiying_comm/zhiying_comm.dart'; |
|
|
|
import 'package:zhiying_base_widget/widgets/share/models/share_select_pic_model.dart'; |
|
|
|
import 'package:zhiying_base_widget/template/goods_share_template/goods_share_template.dart'; |
|
|
|
|
|
|
|
class ShareAlertSelect extends StatefulWidget { |
|
|
|
final String skipIdentifier; |
|
|
|
final bool isContentShow; |
|
|
|
final ShareDataModel model; |
|
|
|
final bool isPicShow; |
|
|
|
final ShareSelectPicModel selectPicModel; |
|
|
|
|
|
|
|
const ShareAlertSelect(this.model, this.skipIdentifier, |
|
|
|
{Key key, this.isContentShow = false, this.selectPicModel, this.isPicShow}) |
|
|
|
: super(key: key); // 中间视图 |
|
|
|
|
|
|
|
@override |
|
|
|
_ShareAlertSelectState createState() => _ShareAlertSelectState(); |
|
|
|
} |
|
|
|
|
|
|
|
class _ShareAlertSelectState extends State<ShareAlertSelect> { |
|
|
|
ShareAlertModel _iconModel; |
|
|
|
bool isPicShow; |
|
|
|
ShareSelectPicModel selectPicModel; |
|
|
|
GlobalKey _globalKey = GlobalKey(); |
|
|
|
|
|
|
|
@override |
|
|
|
void initState() { |
|
|
|
NetUtil.request('/api/v1/mod/${widget.skipIdentifier}', method: NetMethod.GET, |
|
|
|
onCache: (data) { |
|
|
|
// try{ |
|
|
|
// _parseData(data); |
|
|
|
// }catch(e){ |
|
|
|
// print(e); |
|
|
|
// } |
|
|
|
}, onSuccess: (data) { |
|
|
|
print(data); |
|
|
|
_parseData(data); |
|
|
|
}, onError: (err) {}); |
|
|
|
|
|
|
|
if (!EmptyUtil.isEmpty(widget.isPicShow)) { |
|
|
|
isPicShow = widget.isPicShow; |
|
|
|
} else { |
|
|
|
isPicShow = false; |
|
|
|
} |
|
|
|
selectPicModel = widget.selectPicModel; |
|
|
|
super.initState(); |
|
|
|
} |
|
|
|
|
|
|
|
void _parseData(Map<String, dynamic> data) { |
|
|
|
List modList = data['mod_list']; |
|
|
|
Map d = modList.first; |
|
|
|
if (d != null) { |
|
|
|
String dString = d['data']; |
|
|
|
_iconModel = |
|
|
|
ShareAlertModel.fromJson(Map<String, dynamic>.from(jsonDecode(dString))); |
|
|
|
|
|
|
|
setState(() {}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
_selectPic(List<SharePicItem> picList, int position) async { |
|
|
|
ShareDataModel model = ShareDataModel(); |
|
|
|
model.image = []; |
|
|
|
for (int i = 0; i < picList.length; i++) { |
|
|
|
if (picList[i].select) { |
|
|
|
if (i == 0) { |
|
|
|
ShareDataModel shareDataModel = await _updateModel(_globalKey); |
|
|
|
model.poster = shareDataModel.poster; |
|
|
|
} else { |
|
|
|
model.image.add(picList[i].pic); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
EventUtil.instance.fire(model); |
|
|
|
} |
|
|
|
|
|
|
|
Future<ShareDataModel> _updateModel(GlobalKey _globalKey) async { |
|
|
|
ShareDataModel _shareModel = ShareDataModel(); |
|
|
|
BuildContext buildContext = _globalKey.currentContext; |
|
|
|
if (null != buildContext) { |
|
|
|
RenderRepaintBoundary boundary = buildContext.findRenderObject(); |
|
|
|
ui.Image image = await boundary.toImage(pixelRatio: 1); |
|
|
|
// 注意:png是压缩后格式,如果需要图片的原始像素数据,请使用rawRgba |
|
|
|
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png); |
|
|
|
Uint8List pngBytes = byteData.buffer.asUint8List(); |
|
|
|
_shareModel.poster = pngBytes; |
|
|
|
} else { |
|
|
|
_shareModel.poster = null; |
|
|
|
} |
|
|
|
// _shareModel.content = _isContentSelected ? _content : ''; |
|
|
|
return _shareModel; |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
return WillPopScope( |
|
|
|
onWillPop: () async { |
|
|
|
Loading.dismiss(); |
|
|
|
Navigator.canPop(context); |
|
|
|
return true; |
|
|
|
}, |
|
|
|
child: GestureDetector( |
|
|
|
child: Scaffold( |
|
|
|
backgroundColor: Colors.transparent, |
|
|
|
body: BackdropFilter( |
|
|
|
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), //背景 |
|
|
|
child: Container( |
|
|
|
child: Column( |
|
|
|
children: <Widget>[ |
|
|
|
widget.isContentShow |
|
|
|
? Expanded( |
|
|
|
child: Center(child: ShareAlertContent(_iconModel)), |
|
|
|
) |
|
|
|
: Container(), |
|
|
|
isPicShow |
|
|
|
? Expanded( |
|
|
|
child: Swiper( |
|
|
|
loop: false, |
|
|
|
itemBuilder: (BuildContext context, int index) { |
|
|
|
Widget picWidget; |
|
|
|
if (index == 0) { |
|
|
|
picWidget = Expanded( |
|
|
|
child: Transform.scale( |
|
|
|
alignment: Alignment.center, |
|
|
|
scale: 0.75, |
|
|
|
child: GoodsShareTemplate( |
|
|
|
selectPicModel.posterModel, |
|
|
|
contentKey: _globalKey, |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} else { |
|
|
|
picWidget = CachedNetworkImage( |
|
|
|
imageUrl: selectPicModel.picList[index].pic, |
|
|
|
fit: BoxFit.fitWidth, |
|
|
|
); |
|
|
|
} |
|
|
|
return Container( |
|
|
|
alignment: Alignment.bottomCenter, |
|
|
|
margin: EdgeInsets.only(top: 50, bottom: 10), |
|
|
|
child: Stack( |
|
|
|
children: <Widget>[ |
|
|
|
picWidget, |
|
|
|
// CachedNetworkImage( |
|
|
|
// imageUrl: selectPicModel.picList[index].pic, |
|
|
|
// fit: BoxFit.fitWidth, |
|
|
|
// ), |
|
|
|
Positioned( |
|
|
|
bottom: 10, |
|
|
|
right: 15, |
|
|
|
child: GestureDetector( |
|
|
|
onTap: () { |
|
|
|
selectPicModel.picList[index].select = |
|
|
|
!selectPicModel.picList[index].select; |
|
|
|
setState(() {}); |
|
|
|
_selectPic(selectPicModel.picList, index); |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
alignment: Alignment.center, |
|
|
|
decoration: BoxDecoration( |
|
|
|
borderRadius: BorderRadius.circular(50), |
|
|
|
color: selectPicModel.picList[index].select |
|
|
|
? Colors.red |
|
|
|
: Colors.grey, |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
CupertinoIcons.check_mark, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
) |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
}, |
|
|
|
itemCount: selectPicModel.picList.length, |
|
|
|
viewportFraction: 0.8, |
|
|
|
scale: 0.8, |
|
|
|
), |
|
|
|
) |
|
|
|
: Container(), |
|
|
|
_ShareAlertContent( |
|
|
|
widget.model, widget.skipIdentifier, _iconModel, isPicShow), |
|
|
|
], |
|
|
|
), |
|
|
|
), // 模糊化 |
|
|
|
), |
|
|
|
), |
|
|
|
onTap: () { |
|
|
|
// Navigator.of(context).pop(); |
|
|
|
}, |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
class _ShareAlertContent extends StatefulWidget { |
|
|
|
final ShareDataModel model; |
|
|
|
final String skipIdentifier; |
|
|
|
final ShareAlertModel iconModel; |
|
|
|
final bool isSelectPic; |
|
|
|
|
|
|
|
const _ShareAlertContent( |
|
|
|
this.model, this.skipIdentifier, this.iconModel, this.isSelectPic, |
|
|
|
{Key key}) |
|
|
|
: super(key: key); |
|
|
|
|
|
|
|
@override |
|
|
|
_ShareAlertContentState createState() => _ShareAlertContentState(); |
|
|
|
} |
|
|
|
|
|
|
|
class _ShareAlertContentState extends State<_ShareAlertContent> { |
|
|
|
StreamSubscription listen; |
|
|
|
bool isSelectPic; |
|
|
|
|
|
|
|
ShareDataModel _shareDataModel; |
|
|
|
|
|
|
|
@override |
|
|
|
void dispose() { |
|
|
|
// TODO: implement dispose |
|
|
|
listen?.cancel(); |
|
|
|
super.dispose(); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
void initState() { |
|
|
|
// TODO: implement initState |
|
|
|
isSelectPic = widget.isSelectPic; |
|
|
|
|
|
|
|
if (isSelectPic) { |
|
|
|
_shareDataModel = null; |
|
|
|
} else { |
|
|
|
_shareDataModel = widget?.model; |
|
|
|
} |
|
|
|
listen = EventUtil.instance.on<ShareDataModel>().listen((ShareDataModel event) { |
|
|
|
if (isSelectPic) { |
|
|
|
_shareDataModel = event; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
super.initState(); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
return GestureDetector( |
|
|
|
onTap: () {}, |
|
|
|
child: Container( |
|
|
|
width: double.infinity, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.white, |
|
|
|
borderRadius: BorderRadius.only( |
|
|
|
topLeft: Radius.circular(12), |
|
|
|
topRight: Radius.circular(12), |
|
|
|
), |
|
|
|
), |
|
|
|
child: SafeArea( |
|
|
|
top: false, |
|
|
|
child: Column( |
|
|
|
children: <Widget>[ |
|
|
|
Container( |
|
|
|
margin: EdgeInsets.only(top: 8, bottom: 8), |
|
|
|
width: 62, |
|
|
|
height: 4, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Color(0xffd8d8d8), borderRadius: BorderRadius.circular(2)), |
|
|
|
), |
|
|
|
Text( |
|
|
|
'分享至', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 15, color: Color(0xff333333), fontWeight: FontWeight.bold), |
|
|
|
), |
|
|
|
Container( |
|
|
|
margin: EdgeInsets.only(left: 12, right: 12, top: 10, bottom: 10), |
|
|
|
child: _createIcons(), |
|
|
|
), |
|
|
|
GestureDetector( |
|
|
|
child: Container( |
|
|
|
margin: EdgeInsets.only(left: 12, right: 12, bottom: 10), |
|
|
|
padding: EdgeInsets.all(12), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Color(0xfff3f3f3), borderRadius: BorderRadius.circular(8)), |
|
|
|
child: Center( |
|
|
|
child: Text( |
|
|
|
'取消', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
color: Color(0xff999999)), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
onTap: () { |
|
|
|
Navigator.of(context).pop(); |
|
|
|
}, |
|
|
|
) |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
Widget _createIcons() { |
|
|
|
return Wrap( |
|
|
|
spacing: 10, |
|
|
|
runSpacing: 10, |
|
|
|
children: widget.iconModel?.icons?.map((item) { |
|
|
|
return _createIcon(item); |
|
|
|
})?.toList() ?? |
|
|
|
[], |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
Widget _createIcon(ShareIconModel item) { |
|
|
|
return GestureDetector( |
|
|
|
child: Container( |
|
|
|
width: 60, |
|
|
|
child: Column( |
|
|
|
children: <Widget>[ |
|
|
|
Container( |
|
|
|
width: 40, |
|
|
|
height: 40, |
|
|
|
child: CachedNetworkImage( |
|
|
|
imageUrl: item.icon, |
|
|
|
fit: BoxFit.contain, |
|
|
|
), |
|
|
|
), |
|
|
|
Padding( |
|
|
|
padding: const EdgeInsets.only(top: 2, bottom: 2), |
|
|
|
child: Text( |
|
|
|
item.name, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12, color: Color(0xff333333), fontWeight: FontWeight.bold), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
onTap: () async { |
|
|
|
//检查是否有存储权限 |
|
|
|
var status = await Permission.storage.status; |
|
|
|
if (!status.isGranted) { |
|
|
|
status = await Permission.storage.request(); |
|
|
|
print(status); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (item.type == 'wx') { |
|
|
|
_shareByMob(ShareSDKPlatforms.wechatSession); |
|
|
|
} else if (item.type == 'pyq') { |
|
|
|
_shareByMob(ShareSDKPlatforms.wechatTimeline); |
|
|
|
} else if (item.type == 'qq') { |
|
|
|
_shareByMob(ShareSDKPlatforms.qq); |
|
|
|
} else if (item.type == 'qq_space') { |
|
|
|
_shareByMob(ShareSDKPlatforms.qZone); |
|
|
|
} else if (item.type == 'weibo') { |
|
|
|
_shareByMob(ShareSDKPlatforms.sina); |
|
|
|
} else if (item.type == 'more_setting') { |
|
|
|
_shareBySystem(); |
|
|
|
} |
|
|
|
}, |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// mob分享,只能单图分享,多图分享调用系统分享 |
|
|
|
void _shareByMob(ShareSDKPlatform plateform) async { |
|
|
|
if (isSelectPic && |
|
|
|
EmptyUtil.isEmpty(_shareDataModel) && |
|
|
|
EmptyUtil.isEmpty(_shareDataModel?.poster) && |
|
|
|
EmptyUtil.isEmpty(_shareDataModel?.image)) { |
|
|
|
Fluttertoast.showToast(msg: '请选择分享图片'); |
|
|
|
return; |
|
|
|
} |
|
|
|
int count = 0; |
|
|
|
if (_shareDataModel.poster != null) { |
|
|
|
count++; |
|
|
|
} |
|
|
|
count += (_shareDataModel?.image?.length ?? 0); |
|
|
|
// 多图分享 |
|
|
|
if (count > 1) { |
|
|
|
_shareMultipleImages(); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
Loading.show(context); |
|
|
|
Timer(Duration(milliseconds: 2000), () { |
|
|
|
Loading.dismiss(); |
|
|
|
}); |
|
|
|
|
|
|
|
SSDKMap params; |
|
|
|
if (_shareDataModel.poster != null) { |
|
|
|
String path = await _savePoster(); |
|
|
|
if (path != null && path != '') { |
|
|
|
params = SSDKMap() |
|
|
|
..setGeneral( |
|
|
|
_shareDataModel?.title ?? '', |
|
|
|
_shareDataModel?.content ?? '', |
|
|
|
Platform.isIOS ? path : null, |
|
|
|
null, |
|
|
|
Platform.isAndroid ? path : null, |
|
|
|
null, |
|
|
|
null, |
|
|
|
null, |
|
|
|
null, |
|
|
|
null, |
|
|
|
SSDKContentTypes.image, |
|
|
|
); |
|
|
|
} |
|
|
|
} else { |
|
|
|
var type = SSDKContentTypes.auto; |
|
|
|
|
|
|
|
if (_shareDataModel?.image?.first != null && _shareDataModel?.url != null) { |
|
|
|
type = SSDKContentTypes.webpage; |
|
|
|
} else if (_shareDataModel?.image?.first != null) { |
|
|
|
type = SSDKContentTypes.image; |
|
|
|
} else if (_shareDataModel?.title != null || _shareDataModel?.content != null) { |
|
|
|
type = SSDKContentTypes.text; |
|
|
|
} |
|
|
|
if (plateform == ShareSDKPlatforms.qZone) { |
|
|
|
_shareDataModel?.title = null; |
|
|
|
type = SSDKContentTypes.message; |
|
|
|
} |
|
|
|
|
|
|
|
params = SSDKMap() |
|
|
|
..setGeneral( |
|
|
|
_shareDataModel?.title ?? '', |
|
|
|
_shareDataModel?.content ?? '', |
|
|
|
Platform.isIOS ? _shareDataModel.image : null, |
|
|
|
Platform.isAndroid ? _shareDataModel?.image?.first : null, |
|
|
|
null, |
|
|
|
_shareDataModel.url, |
|
|
|
null, |
|
|
|
null, |
|
|
|
null, |
|
|
|
null, |
|
|
|
type, |
|
|
|
); |
|
|
|
} |
|
|
|
SharesdkPlugin.share(plateform, params, |
|
|
|
(SSDKResponseState state, Map userdata, Map contentEntity, SSDKError error) { |
|
|
|
print(error); |
|
|
|
if (state == SSDKResponseState.Fail) { |
|
|
|
Fluttertoast.showToast(msg: '分享失败'); |
|
|
|
} else if (state == SSDKResponseState.Success) { |
|
|
|
//Fluttertoast.showToast(msg: '分享成功'); |
|
|
|
} else if (state == SSDKResponseState.Cancel) { |
|
|
|
Fluttertoast.showToast(msg: '取消分享'); |
|
|
|
} |
|
|
|
Logger.debug('${state}, ${error.rawData}'); |
|
|
|
Loading.dismiss(); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// 系统分享,只能分享图片或者文字,不能组合分享 |
|
|
|
void _shareBySystem() async { |
|
|
|
if (isSelectPic && |
|
|
|
EmptyUtil.isEmpty(_shareDataModel) && |
|
|
|
EmptyUtil.isEmpty(_shareDataModel?.poster) && |
|
|
|
EmptyUtil.isEmpty(_shareDataModel?.image)) { |
|
|
|
Fluttertoast.showToast(msg: '请选择分享图片'); |
|
|
|
return; |
|
|
|
} |
|
|
|
int count = 0; |
|
|
|
if (_shareDataModel.poster != null) { |
|
|
|
count++; |
|
|
|
} |
|
|
|
count += (_shareDataModel?.image?.length ?? 0); |
|
|
|
// 多图分享 |
|
|
|
if (count > 1) { |
|
|
|
_shareMultipleImages(); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (_shareDataModel.poster != null) { |
|
|
|
String path = await _savePoster(); |
|
|
|
if (path != null && path != '') { |
|
|
|
ShareExtend.share(path, 'image'); |
|
|
|
} |
|
|
|
} else { |
|
|
|
ShareExtend.share(_shareDataModel.content, 'text'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
Future<String> _savePoster() async { |
|
|
|
String path; |
|
|
|
if (_shareDataModel.poster != null) { |
|
|
|
// 检查并请求权限 |
|
|
|
var status = await Permission.storage.status; |
|
|
|
if (status != PermissionStatus.granted) { |
|
|
|
status = await Permission.storage.request(); |
|
|
|
} |
|
|
|
if (status == PermissionStatus.denied) { |
|
|
|
Fluttertoast.showToast(msg: '暂无权限,分享失败'); |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
// 保存到本地路径 |
|
|
|
final tempDir = await getTemporaryDirectory(); |
|
|
|
final file = await File('${tempDir.path}/image.jpg').create(); |
|
|
|
file.writeAsBytesSync(_shareDataModel.poster); |
|
|
|
|
|
|
|
path = file.path; |
|
|
|
Logger.debug(file.path); |
|
|
|
} catch (err, s) { |
|
|
|
Logger.error(err.toString(), s.toString()); |
|
|
|
Fluttertoast.showToast(msg: '分享失败'); |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
return path; |
|
|
|
} |
|
|
|
|
|
|
|
// 多图分享,调用系统分享 |
|
|
|
void _shareMultipleImages() async { |
|
|
|
List<String> paths = List(); |
|
|
|
String path = await _savePoster(); |
|
|
|
if (path != null && path != '') { |
|
|
|
paths.add(path); |
|
|
|
} |
|
|
|
|
|
|
|
Loading.show(context); |
|
|
|
List<String> downPaths = await ImageDownloadUtil.download(_shareDataModel.image); |
|
|
|
paths.addAll(downPaths); |
|
|
|
ShareExtend.shareMultiple(paths, "image", subject: ""); |
|
|
|
Loading.dismiss(); |
|
|
|
} |
|
|
|
} |