import 'dart:async'; import 'dart:io'; import 'dart:ui'; import 'package:dio/dio.dart'; import 'package:dio/dio.dart' as adio; import 'dart:convert' as convert; 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/utils/storage.dart'; import 'package:fast/view/component/navi_bar.dart'; import 'package:fast/view/feedback.dart'; import 'package:fast/view/nickname.dart'; import 'package:fast/view/phone.dart'; import 'package:fast/view/web.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:fluwx/fluwx.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'component/alert_widget.dart'; import 'component/share.dart'; import 'component/toast.dart'; class LifecycleEventHandler extends WidgetsBindingObserver { AsyncCallback resumeCallback; AsyncCallback suspendingCallback; LifecycleEventHandler({ required this.resumeCallback, required this.suspendingCallback, }); @override void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { case AppLifecycleState.resumed: resumeCallback(); break; case AppLifecycleState.inactive: break; case AppLifecycleState.paused: break; case AppLifecycleState.detached: break; } super.didChangeAppLifecycleState(state); } } class Setting extends StatefulWidget { const Setting({Key? key}) : super(key: key); @override State createState() => _SettingState(); } class _SettingState extends State with WidgetsBindingObserver, RouteAware { late UserBean userBean; StreamSubscription? subscription; String agreeUrl = ''; String aboutUrl = ''; String privacyUrl = ''; // final RouteObserver> routeObserver = RouteObserver>(); @override void initState() { userBean = Global().userBean!; super.initState(); initWxApi(); WidgetsBinding widgetsBinding = WidgetsBinding.instance!; widgetsBinding.addObserver(this); getUserInfo(); // WidgetsBinding.instance?.addObserver(LifecycleEventHandler( // resumeCallback: () async {}, suspendingCallback: () async {})); // SystemChannels.lifecycle.setMessageHandler((msg) async { // debugPrint('SystemChannels> $msg'); // if (msg == AppLifecycleState.resumed.toString()) setState(() {}); // }); } @override // ignore: unnecessary_overrides void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); } @override void didChangeDependencies() { super.didChangeDependencies(); Global().routeObserver!.subscribe(this, ModalRoute.of(context)!); } @override void didPopNext() { getUserInfo(); super.didPopNext(); } Future initWxApi() async { bool isSuccess = await registerWxApi( appId: 'wxa8557217acf4f532', universalLink: 'https://api.fast.liveplus.fun/'); if (isSuccess) { subscription = weChatResponseEventHandler.listen((event) { if (event is WeChatPaymentResponse) { } else if (event is WeChatAuthResponse) { print(event.code); bindwx(event.code); } else if (event is WeChatShareResponse) {} }); } } Future bindwx(code) async { try { var data = await HttpUtils.post(Api.outhBind, data: { "app_version": "1.0", "client_type": Platform.isAndroid ? "ANDROID" : "IOS", "client_version": "1.0", "type": "WX", "code": code }); print(data.toString()); // ignore: unused_catch_clause } on DioError catch (e) { showDialog( context: context, barrierDismissible: false, barrierColor: Colors.transparent, builder: (BuildContext context) { return Toast( title: e.response?.data['error_message'], showError: true, content: const SizedBox( width: 0, ), ); }); // if (e.response?.data['error_code'] == 'INVITE_CODE_NOT_EXIST') { // } } getUserInfo(); getUrls(); } Future getUserInfo() async { Map data = await HttpUtils.get(Api.userInfo); UserBean bean = UserBean.fromJson(data); Global().userBean = bean; final prefs = await SharedPreferences.getInstance(); await prefs.setString('userInfo', convert.jsonEncode(data)); if (mounted) { setState(() { userBean = bean; }); } } Future getUrls() async { List urls = await HttpUtils.get(Api.resourcesUrls); setState(() { urls.forEach((element) { if (element['code'] == 'user_agreement') { agreeUrl = element['url']; } if (element['code'] == 'privacy') { privacyUrl = element['url']; } if (element['code'] == 'about') { aboutUrl = element['url']; } }); }); } Future deleteAccount() async { await HttpUtils.post(Api.delAccount); Global().token = ""; StorageUtil().prefs!.clear(); Navigator.of(context).pop(); Get.back(); Global().mainPage!.logout(); } Future clearFast() async { await HttpUtils.post(Api.clearFast); Navigator.of(context).pop(); Get.back(); } @override void dispose() { subscription!.cancel(); Global().routeObserver!.unsubscribe(this); super.dispose(); } // Future initWxApi() async { // 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); // login(event.code); // } else if (event is WeChatShareResponse) {} // }); // } // } showShare() { showDialog( context: context, barrierDismissible: false, barrierColor: const Color(0xF2000D1F), builder: (BuildContext context) { return Share( type: 'me', ); }); } Future share() async { // 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.asset("assets/images/3days_bg.png"))); } @override Widget build(BuildContext context) { SizeFit.initialize(context); EdgeInsets safePadding = MediaQuery.of(context).padding; return Material( color: kBgColor, child: Stack( children: [ SizedBox( height: MediaQuery.of(context).size.height, child: SingleChildScrollView( child: Column(children: [ Container( margin: EdgeInsets.only(top: safePadding.top + 40.px), ), Container( margin: EdgeInsets.fromLTRB(14.px, 8.px, 14.px, 8.px), padding: EdgeInsets.only(left: 18.px, right: 18.px), decoration: groupDecoration(), child: Column( children: [ GestureDetector( onTap: () { showPicker(); }, child: Container( height: 60.px, alignment: Alignment.center, decoration: borderBottomDecoration(), child: Row( children: [ Expanded( child: Text( '头像', style: titleStyle(), ), ), ClipOval( child: Image.network( userBean.avatar!, width: 40.px, height: 40.px, fit: BoxFit.cover, ), ) ], ), ), ), GestureDetector( onTap: () { Get.to(() => const Nickname()); }, child: Container( height: 54.px, alignment: Alignment.center, child: Row( children: [ Expanded( child: Text( '昵称', style: titleStyle(), )), Text( userBean.nickname!, style: subTitleStyle(), ) ], ), ), ) ], ), ), Container( margin: EdgeInsets.fromLTRB(14.px, 8.px, 14.px, 8.px), padding: EdgeInsets.only(left: 18.px, right: 18.px), decoration: groupDecoration(), child: Column( children: [ GestureDetector( onTap: () { showShare(); }, child: Container( height: 60.px, alignment: Alignment.center, decoration: borderBottomDecoration(), child: Row( children: [ Text( '邀请码', style: titleStyle(), ), SizedBox( width: 15.px, ), Expanded( child: Text( userBean.inviteCode!, style: subTitleStyle(), )), Text( '分享给好友', style: TextStyle( color: kThemeColor, fontSize: 14.px), ), SizedBox( width: 6.px, ), Text( '+3', style: TextStyle( color: const Color(0x99FFFFFF), fontSize: 12.px, fontFamily: 'Exo2', ), ), SizedBox( width: 2.px, ), Image.asset( 'assets/images/stone.png', width: 14.px, height: 14.px, ) ], ), ), ), GestureDetector( child: Container( height: 54.px, alignment: Alignment.center, child: Row( children: [ Text( '受邀码', style: titleStyle(), ), SizedBox( width: 15.px, ), Expanded( child: Text( '还没有哦', style: subTitleStyle(), )) ], ), ), ) ], ), ), Container( margin: EdgeInsets.fromLTRB(14.px, 8.px, 14.px, 8.px), padding: EdgeInsets.only(left: 18.px, right: 18.px), decoration: groupDecoration(), child: Column( children: [ GestureDetector( onTap: () { if (userBean.mobieBind) { return; } Get.to(() => Phone( type: 2, )); }, child: Container( height: 54.px, alignment: Alignment.center, decoration: borderBottomDecoration(), child: Row( children: [ Expanded( child: Text( '手机号', style: titleStyle(), )), Text( userBean.mobieBind ? '已绑定' : '立即绑定', style: subTitleStyle(), ) ], ), ), ), GestureDetector( onTap: () { if (userBean.wxBind) { return; } sendWeChatAuth(scope: 'snsapi_userinfo'); }, child: Container( height: 54.px, alignment: Alignment.center, child: Row( children: [ Expanded( child: Text( '绑定微信', style: titleStyle(), )), Text( userBean.wxBind ? '已绑定' : '立即绑定', style: subTitleStyle(), ) ], ), ), ) ], ), ), Container( margin: EdgeInsets.fromLTRB(14.px, 8.px, 14.px, 8.px), padding: EdgeInsets.only(left: 18.px, right: 18.px), decoration: groupDecoration(), child: Column( children: [ GestureDetector( onTap: () { Get.to(() => const FeedbackPage()); }, child: Container( height: 54.px, alignment: Alignment.center, decoration: borderBottomDecoration(), child: Row( children: [ Expanded( child: Text( '意见反馈', style: titleStyle(), )), Image.asset( 'assets/images/next.png', width: 24.px, height: 24.px, ) ], ), ), ), GestureDetector( onTap: () { Get.to(() => Web( title: '用户协议', url: agreeUrl, )); }, child: Container( height: 54.px, alignment: Alignment.center, decoration: borderBottomDecoration(), child: Row( children: [ Expanded( child: Text( '用户协议', style: titleStyle(), )), Image.asset( 'assets/images/next.png', width: 24.px, height: 24.px, ) ], ), ), ), GestureDetector( onTap: () { Get.to(() => Web( title: '隐私政策', url: privacyUrl, )); }, child: Container( height: 54.px, alignment: Alignment.center, decoration: borderBottomDecoration(), child: Row( children: [ Expanded( child: Text( '隐私政策', style: titleStyle(), )), Image.asset( 'assets/images/next.png', width: 24.px, height: 24.px, ) ], ), ), ), GestureDetector( onTap: () { Get.to(() => Web( title: '关于间歇性断食', url: aboutUrl, )); }, child: Container( height: 54.px, alignment: Alignment.center, child: Row( children: [ Expanded( child: Text( '关于间歇性断食', style: titleStyle(), )), Image.asset( 'assets/images/next.png', width: 24.px, height: 24.px, ) ], ), ), ) ], ), ), GestureDetector( onTap: () { showDialog( context: context, barrierDismissible: false, barrierColor: const Color(0xF2000D1F), builder: (BuildContext context) { return AlertWidget( title: '确定要退出吗?', confirm: '确定', confirmCallback: () { Global().token = ""; StorageUtil().prefs!.clear(); Navigator.of(context).pop(); Get.back(); Global().mainPage!.logout(); }); }); }, child: Container( width: 347.px, height: 50.px, margin: EdgeInsets.only(top: 8.px, bottom: 0.px), decoration: BoxDecoration( border: Border.all(color: const Color(0x66AAFF00)), borderRadius: BorderRadius.all(Radius.circular(25.px))), alignment: Alignment.center, child: Text( '安全退出账号', style: TextStyle( color: kThemeColor, fontSize: 16.px, fontWeight: FontWeight.bold), ), ), ), SizedBox( height: 28.px, ), GestureDetector( onTap: () { showDialog( context: context, barrierDismissible: false, barrierColor: const Color(0xF2000D1F), builder: (BuildContext context) { return AlertWidget( title: '确定要注销此账号吗?', confirm: '确定', confirmCallback: () { deleteAccount(); }); }); }, child: Text( '注销账号', style: TextStyle( color: const Color(0xFFC4CCDA), fontSize: 14.px), ), ), SizedBox( height: 28.px, ), GestureDetector( onTap: () { showDialog( context: context, barrierDismissible: false, barrierColor: const Color(0xF2000D1F), builder: (BuildContext context) { return AlertWidget( title: '确定要清除断食记录吗?', confirm: '确定', confirmCallback: () { clearFast(); }); }); }, child: Text( '清除断食记录', style: TextStyle( color: const Color(0xFFC4CCDA), fontSize: 14.px), ), ), SizedBox( height: 70.px, ) ]))), NaviBar( title: '设置', closeCallback: () { Get.back(); }), Positioned( left: 0, bottom: 0, child: IgnorePointer( child: Container( width: 375.px, height: 200.px, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Color(0x00050F1A), Color(0xFF050F1A)])), )), ) ], ), ); } showPicker() { showCupertinoModalPopup( context: context, builder: (BuildContext context) => CupertinoActionSheet( title: const Text('选择操作'), actions: [ CupertinoActionSheetAction( onPressed: () { getImageFromGallery(); Navigator.pop(context); }, child: const Text('相册选择')), CupertinoActionSheetAction( onPressed: () { getImageFromCamera(); Navigator.pop(context); }, child: const Text('拍照选择')) ], cancelButton: CupertinoActionSheetAction( child: const Text('取消'), onPressed: () { Navigator.pop(context); }, ), )); } Future getImageFromCamera() async { ImagePicker picker = ImagePicker(); var image = await picker.pickImage(source: ImageSource.camera, imageQuality: 50); if (image != null) { uploadImage(image as XFile); } return; } Future getImageFromGallery() async { ImagePicker picker = ImagePicker(); var image = await picker.pickImage(source: ImageSource.gallery, imageQuality: 50); uploadImage(image as XFile); return; } Future uploadImage(XFile obj) async { Map data = await HttpUtils.get(Api.ossFormUpload, params: {'type': 'AVATAR', 'file_ext': 'png'}); Dio dio = Dio(); Map map = data['fields']; map['file'] = await adio.MultipartFile.fromFile(obj.path, filename: 'avatar.png'); adio.FormData formData = adio.FormData.fromMap(map); adio.Response response = await dio.post(data['upload_url'], data: formData); var data2 = await HttpUtils.post(Api.userInfo, data: {'avatar': data['view_url']}); if (data2 != null) { getUserInfo(); } } BoxDecoration borderBottomDecoration() { return const BoxDecoration( border: Border(bottom: BorderSide(color: Color(0x1AFFFFFF)))); } BoxDecoration groupDecoration() { return BoxDecoration( color: const Color(0x14C4CCDA), borderRadius: BorderRadius.all(Radius.circular(16.px))); } TextStyle titleStyle() { return TextStyle( color: Colors.white, fontSize: 14.px, fontWeight: FontWeight.bold); } TextStyle subTitleStyle() { return TextStyle(color: const Color(0x66FFFFFF), fontSize: 14.px); } }