| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754 |
- import 'dart:async';
- import 'dart:convert';
- import 'dart:io';
- import 'dart:typed_data';
- import 'package:app_settings/app_settings.dart';
- import 'package:dio/dio.dart';
- import 'package:fast/constants.dart';
- import 'package:fast/model/model.dart';
- import 'package:fast/utils/api.dart';
- import 'package:fast/utils/global.dart';
- import 'package:fast/utils/http_utils.dart';
- import 'package:fast/utils/size_fit.dart';
- import 'package:fast/view/component/toast.dart';
- import 'package:flutter/foundation.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/services.dart';
- import 'package:fluwx/fluwx.dart';
- import 'package:image_gallery_saver/image_gallery_saver.dart';
- import 'package:permission_handler/permission_handler.dart';
- import 'package:screenshot/screenshot.dart';
- import 'alert_widget.dart';
- import 'challenge_result.dart';
- import 'loading.dart';
- // import 'package:widget_to_image/widget_to_image.dart';
- // ignore: must_be_immutable
- class Share extends StatefulWidget {
- String type;
- FastResultBean fastResultBean = FastResultBean();
- Share({Key? key, required this.type, FastResultBean? resultBean})
- : super(key: key) {
- if (resultBean != null) {
- fastResultBean = resultBean;
- }
- }
- @override
- State<Share> createState() => _ShareState();
- }
- const baseUrl = 'https://api.fast.dev.liveplus.fun/static/image/';
- class _ShareState extends State<Share> {
- Uint8List? byteData;
- Uint8List? qrcodeData;
- ScreenshotController screenshotController = ScreenshotController();
- @override
- void initState() {
- getQRCode();
- super.initState();
- }
- Future getQRCode() async {
- Dio dio = Dio();
- // 注意:这里使用bytes
- dio.options.responseType = ResponseType.bytes;
- // 如果headers有东西,则添加
- Map<String, dynamic> headers = {
- 'Authorization': 'Bearer ${Global().token}'
- };
- dio.options.headers = headers;
- try {
- String platform = Platform.isIOS?'IOS':'ANDROID';
- String path = Api.qrcode+'client='+platform;
- Response response = await dio.get(path);
- final Uint8List bytes = consolidateHttpClientResponseBytes(response.data);
- setState(() {
- qrcodeData = bytes;
- });
- Timer(const Duration(seconds: 2), () {
- loadData();
- });
- } catch (e) {
- return await null;
- }
- // var data = await HttpUtils.get(Api.qrcode);
- // if (data != null) {
- // String aa = data as String;
- // Uint8List bytes = encode(aa);
- // setState(() {
- // qrcodeData = bytes;
- // });
- // }
- // Timer(const Duration(seconds: 2), () {
- // loadData();
- // });
- }
- consolidateHttpClientResponseBytes(List<int> data) {
- // response.contentLength is not trustworthy when GZIP is involved
- // or other cases where an intermediate transformer has been applied
- // to the stream.
- final List<List<int>> chunks = <List<int>>[];
- int contentLength = 0;
- chunks.add(data);
- contentLength += data.length;
- final Uint8List bytes = Uint8List(contentLength);
- int offset = 0;
- for (List<int> chunk in chunks) {
- bytes.setRange(offset, offset + chunk.length, chunk);
- offset += chunk.length;
- }
- return bytes;
- }
- Uint8List encode(String s) {
- var encodedString = utf8.encode(s);
- var encodedLength = encodedString.length;
- var data = ByteData(encodedLength + 4);
- data.setUint32(0, encodedLength, Endian.big);
- var bytes = data.buffer.asUint8List();
- bytes.setRange(4, encodedLength + 4, encodedString);
- return bytes;
- }
- void loadData() {
- screenshotController.capture().then((value) {
- setState(() {
- byteData = value as Uint8List;
- });
- });
- }
- // Future loadData() async{
- // ByteData data = await WidgetToImage.widgetToImage(detail());
- // setState(() {
- // byteData=data;
- // });
- // }
- Future share(int type) async {
- if (byteData == null) {
- return;
- }
- if (type == 2) {
- var status = await Permission.storage.request().isGranted;
- if (Platform.isIOS) {
- status = await Permission.photos.request().isGranted;
- var perStatus = await Permission.photos.status;
- if (perStatus.isLimited) {
- status = true;
- }
- }
- if (status == true) {
- var result = await ImageGallerySaver.saveImage(byteData!);
- //toast 保存成功
- Navigator.of(context).pop();
- showDialog(
- context: context,
- barrierDismissible: false,
- barrierColor: Colors.transparent,
- builder: (BuildContext context) {
- return Toast(
- title: '分享图已保存',
- content: const SizedBox(
- width: 0,
- ),
- );
- });
- } else {
- //处理拒绝的情况
- showDialog(
- context: context,
- barrierDismissible: false,
- barrierColor: const Color(0xF2000D1F),
- builder: (BuildContext context) {
- return AlertWidget(
- title: '为了确保您的完整体验\n请开启fast16cc使用你的相册访问权限',
- confirm: '去开启',
- confirmCallback: () {
- AppSettings.openNotificationSettings();
- Navigator.of(context).pop();
- });
- });
- }
- return;
- }
- bool isSuccess = await registerWxApi(
- appId: 'wxa8557217acf4f532',
- universalLink: 'https://api.fast.liveplus.fun/');
- if (isSuccess) {
- weChatResponseEventHandler.listen((event) {
- if (event is WeChatPaymentResponse) {
- } else if (event is WeChatAuthResponse) {
- print(event.code);
- } else if (event is WeChatShareResponse) {
- print(event.toString());
- }
- });
- }
- shareToWeChat(
- // WeChatShareTextModel("hello world")
- WeChatShareImageModel(WeChatImage.binary(byteData!),
- title: '风靡全球的16/8间歇性断食法\n高效又好玩,等你来挑战~',
- scene: type == 0 ? WeChatScene.SESSION : WeChatScene.TIMELINE));
- }
- @override
- Widget build(BuildContext context) {
- SizeFit.initialize(context);
- return Material(
- child: Stack(
- children: [
- Opacity(
- opacity: 0.01,
- child: Screenshot(
- child: widget.type == 'me' ? detail() : challenge(),
- controller: screenshotController),
- ),
- Container(
- width: 375,
- height: 750,
- color: kBgColor,
- ),
- Opacity(
- opacity: 1,
- child: Container(
- color: kBgColor,
- alignment: Alignment.center,
- child: Stack(
- children: [
- Container(
- margin: EdgeInsets.only(top: 204.px),
- width: 335.px,
- height: 302.px,
- decoration: BoxDecoration(
- color: const Color(0xFF313F52),
- borderRadius:
- BorderRadius.all(Radius.circular(32.px))),
- child: Stack(
- children: [
- Positioned(
- top: 12.px,
- right: 12.px,
- child: GestureDetector(
- onTap: () {
- Navigator.of(context).pop();
- },
- child: Container(
- alignment: Alignment.center,
- decoration: BoxDecoration(
- color: const Color(0x1A000000),
- borderRadius: BorderRadius.all(
- Radius.circular(18.px))),
- width: 36.px,
- height: 36.px,
- child: Image.asset(
- 'assets/images/close.png',
- width: 20.px,
- height: 20.px,
- ),
- ),
- )),
- Positioned(
- left: 0.0,
- right: 0.0,
- bottom: 32.px,
- child: Opacity(
- opacity: byteData == null ? 0.4 : 1.0,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment:
- CrossAxisAlignment.center,
- children: [
- GestureDetector(
- onTap: () {
- share(0);
- },
- child: Column(
- children: [
- Image.asset(
- 'assets/images/share_friend.png',
- width: 60.px,
- height: 60.px,
- ),
- SizedBox(
- height: 10.px,
- ),
- Text(
- '发送给好友',
- style: TextStyle(
- color: Colors.white,
- fontSize: 14.px),
- )
- ],
- ),
- ),
- SizedBox(
- width: 20.px,
- ),
- GestureDetector(
- onTap: () {
- share(1);
- },
- child: Column(
- children: [
- Image.asset(
- 'assets/images/share_timeline.png',
- width: 60.px,
- height: 60.px,
- ),
- SizedBox(
- height: 10.px,
- ),
- Text(
- '分享到朋友圈',
- style: TextStyle(
- color: Colors.white,
- fontSize: 14.px),
- )
- ],
- ),
- ),
- SizedBox(
- width: 20.px,
- ),
- GestureDetector(
- onTap: () {
- share(2);
- },
- child: Column(
- children: [
- Image.asset(
- 'assets/images/share_save.png',
- width: 60.px,
- height: 60.px,
- ),
- SizedBox(
- height: 10.px,
- ),
- Text(
- '保存到相册',
- style: TextStyle(
- color: Colors.white,
- fontSize: 14.px),
- )
- ],
- ),
- )
- ],
- )),
- )
- ],
- ),
- ),
- Container(
- margin: EdgeInsets.only(left: 78.px),
- width: 180.px,
- height: 360.px,
- decoration: BoxDecoration(
- color: const Color(0xFF313F52),
- boxShadow: [
- BoxShadow(
- offset: Offset(0.px, 8.px),
- blurRadius: 16.px,
- color: const Color(0x66000000))
- ]),
- child: previewContent(),
- )
- ],
- )))
- ],
- ),
- );
- }
- Widget previewContent() {
- // return Container(width: 180.px,height: 360.px,color: Colors.pink,);
- if (byteData != null) {
- return Image.memory(
- byteData!,
- width: 180.px,
- height: 360.px,
- fit: BoxFit.cover,
- );
- }
- return Container(
- width: 180.px,
- height: 360.px,
- alignment: Alignment.center,
- margin: EdgeInsets.only(bottom: 20.px),
- child: Loading(
- showBackground: false,
- ));
- }
- challenge() {
- var size = MediaQuery.of(context).size;
- double rate = 1.0;
- if (size.height / size.width > 2.0) {
- if (size.width < 375.px) {
- rate = size.width / 375.px * 0.95;
- }
- } else {
- if (size.height < 750.px) {
- rate = size.height / 750.px * 0.95;
- }
- }
- return Container(
- width: 375.px * rate,
- height: 750.px * rate,
- color: Colors.transparent,
- child: Stack(alignment: AlignmentDirectional.topStart, children: [
- Image.network(
- '${baseUrl}share_${widget.fastResultBean.days}.png',
- width: 375.px * rate,
- height: 750.px * rate,
- fit: BoxFit.cover,
- ),
- Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
- SizedBox(
- width: 375.px * rate,
- height: 42.px * rate,
- ),
- Container(
- width: 80.px * rate,
- height: 80.px * rate,
- decoration: BoxDecoration(boxShadow: [
- BoxShadow(
- offset: Offset(0, 6.px * rate),
- blurRadius: 12.px * rate,
- color: const Color(0x80000D1F))
- ]),
- child: ClipOval(
- child: Image.network(
- Global().userBean!.avatar!,
- width: 80.px * rate,
- height: 80.px * rate,
- fit: BoxFit.cover,
- ),
- ),
- ),
- SizedBox(
- height: 11.px * rate,
- ),
- Text(
- Global().userBean!.nickname!,
- style: TextStyle(
- color: Colors.white,
- fontSize: 20.px * rate,
- height: 1.0,
- fontWeight: FontWeight.bold),
- ),
- Container(
- width: 324.px * rate,
- height: 260.px * rate,
- margin: EdgeInsets.only(top: 94.px * rate),
- decoration: BoxDecoration(
- color: const Color(0xCC000D1F),
- border: Border.all(color: kThemeColor, width: 1),
- borderRadius:
- BorderRadius.all(Radius.circular(34.px * rate)),
- image: const DecorationImage(
- image: AssetImage('assets/images/statistic.png'),
- alignment: Alignment.topRight,
- scale: 2.9)),
- child: Statistic(
- resultBean: widget.fastResultBean,
- rate: rate,
- ))
- ]),
- if (qrcodeData != null)
- Positioned(
- left: 245.px * rate,
- bottom: 106.px * rate,
- child: Image.memory(
- qrcodeData!,
- width: 100.px * rate,
- height: 100.px * rate,
- )),
- Positioned(
- left: 30.px * rate,
- bottom: 102.px * rate,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- SizedBox(
- height: 5.px * rate,
- ),
- Text(
- Global().userBean!.inviteCode!,
- style: TextStyle(
- color: kThemeColor,
- fontSize: 36.px * rate,
- fontFamily: 'Exo2',
- fontWeight: FontWeight.w600),
- ),
- SizedBox(height: 2.px,),
- Text(
- '使用我的邀请码加入',
- style: TextStyle(
- color: Colors.white,
- fontSize: 14.px * rate,
- fontWeight: FontWeight.bold),
- ),
- Row(
- children: [
- Text(
- '立即获得逆龄石',
- style: TextStyle(
- color: Colors.white,
- fontSize: 20.px * rate,
- fontWeight: FontWeight.bold),
- ),
- SizedBox(
- width: 4.px * rate,
- ),
- Text(
- '+3',
- style: TextStyle(
- color: const Color(0x99FFFFFF),
- fontSize: 20.px * rate,
- fontFamily: 'Exo2',
- fontWeight: FontWeight.w600),
- ),
- SizedBox(
- width: 4.px * rate,
- ),
- Image.asset(
- 'assets/images/stone.png',
- width: 24.px * rate,
- height: 24.px * rate,
- )
- ],
- )
- ],
- )),
- ]));
- }
- detail() {
- var size = MediaQuery.of(context).size;
- double rate = 1.0;
- if (size.height / size.width > 2.0) {
- if (size.width < 375.px) {
- rate = size.width / 375.px * 0.95;
- }
- } else {
- if (size.height < 750.px) {
- rate = size.height / 750.px * 0.95;
- }
- }
- return Container(
- width: rate * 375.px,
- height: rate * 750.px,
- color: Colors.transparent,
- child: Stack(
- alignment: AlignmentDirectional.topStart,
- children: [
- Image.network(
- '${baseUrl}share_bg.png',
- width: rate * 375.px,
- height: rate * 750.px,
- fit: BoxFit.cover,
- ),
- Column(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- SizedBox(
- width: rate * 375.px,
- height: rate * 46.px,
- ),
- Container(
- width: rate * 80.px,
- height: rate * 80.px,
- decoration: BoxDecoration(boxShadow: [
- BoxShadow(
- offset: Offset(0, rate * 6.px),
- blurRadius: rate * 12.px,
- color: const Color(0x80000D1F))
- ]),
- child: ClipOval(
- child: Image.network(
- Global().userBean!.avatar!,
- width: rate * 80.px,
- height: rate * 80.px,
- fit: BoxFit.cover,
- ),
- ),
- ),
- SizedBox(
- height: rate * 16.px,
- ),
- Text(
- Global().userBean!.nickname!,
- style: TextStyle(
- color: Colors.white,
- fontSize: rate * 20.px,
- fontWeight: FontWeight.bold),
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Container(
- margin: EdgeInsets.only(top: rate * 8.px),
- padding: EdgeInsets.only(
- left: rate * 9.px, right: rate * 9.px),
- height: rate * 24.px,
- alignment: Alignment.center,
- decoration: BoxDecoration(
- border: Border.all(
- color: const Color(0x80FFFFFF),
- width: 1,
- ),
- borderRadius:
- BorderRadius.all(Radius.circular(rate * 12.px)),
- color: const Color(0x33000D1F)),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Container(
- margin:EdgeInsets.only(bottom: 1.px),
- child: const Text(
- '逆龄石',
- style: TextStyle(color: Colors.white, fontSize: 12),
- ),),
- SizedBox(
- width: rate * 4.px,
- ),
- Image.asset(
- 'assets/images/stone.png',
- width: rate * 16.px,
- height: rate * 16.px,
- ),
- SizedBox(
- width: rate * 4.px,
- ),
- Container(
- margin:EdgeInsets.only(bottom: 2.px),
- child:Text(
- '×${Global().userBean!.rjvBalance}',
- style: TextStyle(
- color: kThemeColor,
- fontSize: rate * 14.px,
- fontFamily: 'Exo2',
- fontWeight: FontWeight.w600),
- ))
- ],
- ),
- )
- ],
- ),
- ],
- ),
- if (qrcodeData != null)
- Positioned(
- left: rate * 245.px,
- bottom: rate * 106.px,
- child: Image.memory(
- qrcodeData!,
- width: rate * 100.px,
- height: rate * 100.px,
- )),
- Positioned(
- left: rate * 2.px,
- top: rate * 244.px,
- child: Text(
- Global().userBean!.nickname!,
- style: TextStyle(
- color: const Color(0xFF000D1F),
- fontSize: rate * 10.px,
- fontWeight: FontWeight.bold),
- )),
- Positioned(
- left: rate * 106.px,
- top: rate * 297.px,
- child: ClipOval(
- child: Image.network(
- Global().userBean!.avatar!,
- width: rate * 32.px,
- height: rate * 32.px,
- fit: BoxFit.cover,
- ),
- )),
- Positioned(
- left: rate * 143.px,
- top: rate * 298.px,
- child: Text(
- Global().userBean!.nickname!,
- style: TextStyle(
- color: Colors.white,
- fontSize: rate * 10.px,
- fontWeight: FontWeight.bold),
- )),
- Positioned(
- left: rate * 30.px,
- bottom: rate * 102.px,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- SizedBox(
- height: rate * 5.px,
- ),
- Text(
- Global().userBean!.inviteCode!,
- style: TextStyle(
- color: kThemeColor,
- fontSize: rate * 36.px,
- fontFamily: 'Exo2',
- fontWeight: FontWeight.w600),
- ),
- SizedBox(
- height: rate * 2.px,
- ),
- Text(
- '使用我的邀请码加入',
- style: TextStyle(
- color: Colors.white,
- fontSize: rate * 14.px,
- fontWeight: FontWeight.bold),
- ),
- Row(
- children: [
- Text(
- '立即获得逆龄石',
- style: TextStyle(
- color: Colors.white,
- fontSize: rate * 20.px,
- fontWeight: FontWeight.bold),
- ),
- SizedBox(
- width: rate * 4.px,
- ),
- Text(
- '+3',
- style: TextStyle(
- color: const Color(0x99FFFFFF),
- fontSize: rate * 20.px,
- fontFamily: 'Exo2',
- fontWeight: FontWeight.w600),
- ),
- SizedBox(
- width: rate * 4.px,
- ),
- Image.asset(
- 'assets/images/stone.png',
- width: rate * 24.px,
- height: rate * 24.px,
- )
- ],
- )
- ],
- )),
- ],
- ));
- }
- }
|