import 'dart:io'; import 'dart:typed_data'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:sport/application.dart'; import 'package:sport/bean/forum.dart'; import 'package:sport/bean/post.dart'; import 'package:sport/pages/social/post_page.dart'; import 'package:sport/pages/social/post_share_page.dart'; import 'package:sport/pages/social/share_webview.dart'; import 'package:sport/provider/user_model.dart'; import 'package:sport/router/navigator_util.dart'; import 'package:sport/services/api/inject_api.dart'; import 'package:sport/services/api/resp.dart'; import 'package:sport/sharesdk/tencent.dart'; import 'package:sport/sharesdk/wechat.dart'; import 'package:sport/utils/toast.dart'; import 'package:sport/widgets/space.dart'; import 'package:umeng_common_sdk/umeng_common_sdk.dart'; import 'package:wechat_kit/wechat_kit.dart'; class MenuShareBottomContent extends StatefulWidget { final String? url; // 复制的那个链接 final bool hasDownload; // 有些又download 有些没download final GlobalKey? poster; // 下载海报... final String shareType; // 什么类型 Img social Link final Post? post; // social 连带的 post final String? hash; // 分享 link 连带的hash final String? file; // 分享 link 连带的hash final bool app; // 分享 是否显示app内功能 MenuShareBottomContent(this.shareType, {this.post, this.url = "", this.hasDownload = false, this.poster, this.hash, this.file, this.app = true}); @override State createState() { return _MenuShareBottomContentState(); } } // shareType : Img / Link / Social class _MenuShareBottomContentState extends State with TencentMixin, WechatMixin, InjectApi { late List> map; Uint8List? postInstance; @override listenWechatShareMsg(ShareMsgResp resp) { Navigator.pop(context); ToastUtil.show("分享成功"); } @override void initState() { super.initState(); map = [ { "value": "微信", "url": "share_icon_wechat", "callBack": () async { if (widget.shareType == "Img") { String path = await initFile(); wechatShareImage(path, "chat"); } else if (widget.shareType == "Link") { wechatShareLink(widget.url ?? "" + "?h=${widget.hash}", "chat", Provider.of(context, listen: false).user.name); } else if (widget.shareType == "Video") { String path = await initFile(); wechatShareVideo(path, "chat"); } UmengCommonSdk.onEvent("share_wechat", {}); } }, { "value": "朋友圈", "url": "share_icon_wechatmonents", "callBack": () async { if (widget.shareType == "Img") { String path = await initFile(); wechatShareImage(path, "friend"); } else if (widget.shareType == "Link") { wechatShareLink(widget.url ?? "" + "?h=${widget.hash}", "friend", Provider.of(context, listen: false).user.name); } UmengCommonSdk.onEvent("share_wechatmonents", {}); } }, { "value": "QQ", "url": "share_icon_qq", "callBack": () async { if (widget.shareType == "Img") { String path = await initFile(); tencentShare(path); } else if (widget.shareType == "Link") { tencentShareLink(widget.url ?? ""); } UmengCommonSdk.onEvent("share_tencent", {}); } }, if(widget.app && openSocial()) { "value": "社区", "url": "share_icon_community", "callBack": () async { UmengCommonSdk.onEvent("share_community", {}); // if(widget.post == null) // return; List buttonList = []; RespList data = await api.getForumIndex(); buttonList = data.results; if (data.results.length > 0) { buttonList.insert(0, new Forum(gameName: "全部")); } if (widget.shareType == "social") { await NavigatorUtil.goPage( context, (contxt) => PostPage( "", post: widget.post, forums: buttonList, )); } else if (widget.shareType == "Link") { await NavigatorUtil.goPage( context, (contxt) => PostPage( "", post: widget.post, url: widget.url, hash: widget.hash, forums: buttonList, )); } else if (widget.shareType == "Img") { String path = await initFile(); print("$path---------------------------------"); await NavigatorUtil.goPage( context, (context) => PostPage( "", image: path, forums: buttonList, )); } Navigator.pop(context, true); } }, if(widget.app && openSocial()) { "value": "社区好友", "url": "share_icon_friends", "callBack": () async { UmengCommonSdk.onEvent("share_friend", {}); if (widget.shareType == "social") { await NavigatorUtil.goPage( context, (context) => PostShareFriendsPage( post: widget.post, )); } else if (widget.shareType == "Link") { // 这里可能得组装一手 link 的 数据 ... await NavigatorUtil.goPage(context, (context) => PostShareFriendsPage(hash: widget.hash)); } else if (widget.shareType == "Img") { String path = await initFile(); String url = (await api.postChatUpload(File(path))).data["url"]; await NavigatorUtil.goPage( context, (context) => PostShareFriendsPage( image: url, )); } Navigator.pop(context, true); } }, if (widget.url?.isNotEmpty == true) { "value": "复制链接", "url": "share_icon_link", "callBack": () { UmengCommonSdk.onEvent("share_copy", {}); Clipboard.setData(ClipboardData(text: widget.url)); ToastUtil.show("复制成功"); } }, if (widget.hasDownload == true) { "value": "下载图片", "url": "share_icon_download", "callBack": () { UmengCommonSdk.onEvent("share_download", {}); _capture().then((file) async {}).whenComplete(() { print("Complete-------------------------------------------------"); }); } }, ]; // 社区暂时先把前面的隐藏掉 if (widget.shareType == "social") { map = map.sublist(map.length - 2, map.length); } } // 封装成灵活的更通用一点... Future initFile() async { if (widget.file?.isNotEmpty == true) return widget.file!; Uint8List pngBytes = await initFileUint8List(); print("$pngBytes------------------------------"); String sTempDir = (await getTemporaryDirectory()).path; bool isDirExist = await Directory(sTempDir).exists(); if (!isDirExist) { Directory(sTempDir).create(); } // QQ分享需要一个确实存在的图片 File file = await File(sTempDir + "/poster-temp-${DateTime.now().millisecondsSinceEpoch}.png").writeAsBytes(pngBytes); Future.delayed(new Duration(milliseconds: 200)); print("[file]:${file.readAsBytesSync().length}---------------${pngBytes.length}----------------"); return file.path; } Future initFileUint8List() async { if(widget.poster == null) return Uint8List.fromList([0]); try { RenderObject? renderObject = widget.poster!.currentContext?.findRenderObject(); //boundary.toImage()转化为ui.Image对象,不会自动为包裹的组件添加背景,不设置可能会缺失背景 if(renderObject is RenderRepaintBoundary) { RenderRepaintBoundary boundary = renderObject; var image = await boundary.toImage(pixelRatio: window.devicePixelRatio); //将image转化为byteData ByteData? byteData = await image.toByteData(format: ImageByteFormat.png); if (byteData == null) return Uint8List.fromList([0]); //这个对象就是图片数据 Uint8List pngBytes = byteData.buffer.asUint8List(); print("成功生成图片 ----------------------------------------"); return pngBytes; } } catch (e) { print(e); } return Uint8List.fromList([0]); } Future _capture() async { var permission = await Permission.storage.request(); if (!permission.isGranted) { ToastUtil.show("没有保存文件的权限"); return null; } var result ; if (widget.file?.isNotEmpty == true) { result = await ImageGallerySaver.saveFile(widget.file!); }else { Uint8List pngBytes = await initFileUint8List(); result = await ImageGallerySaver.saveImage(pngBytes); } if (result != null && result["isSuccess"] == true) ToastUtil.show("下载成功"); } @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.fromLTRB(12, 23, 24, 17), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( children: [ Expanded( child: Divider( endIndent: 12.0, ), ), Text( "分享至", style: Theme.of(context).textTheme.bodyText2!, ), Expanded( child: Divider( indent: 12.0, ), ) ], ), SizedBox( height: 20.0, ), Wrap( children: map .map((e) => InkWell( child: FractionallySizedBox( widthFactor: .25, child: Container( padding: EdgeInsets.symmetric(horizontal: 5, vertical: 6), child: Center( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset( "lib/assets/img/${e["url"]}.png", width: 44.0, height: 44.0, ), Space( height: 4.0, ), Text( "${e["value"]}", style: Theme.of(context).textTheme.subtitle2, ), // Space(height: 8.0,), ], ), ), )), onTap: () { e["callBack"](); }, )) .toList(), ) ], ), ); } } Future menuShareBottom(BuildContext context, String shareType, {Post? post, String? url, bool hasDownload = true, GlobalKey? poster, String? hash}) { return showModalBottomSheet( context: context, builder: (context) { return MenuShareBottomContent(shareType, post: post, url: url, hasDownload: hasDownload, poster: poster, hash: hash); }, backgroundColor: Colors.white, elevation: 10, shape: RoundedRectangleBorder( borderRadius: BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)), ), ); }