diff --git a/circle_app/assets/images/base/icon_login.png b/circle_app/assets/images/base/icon_login.png new file mode 100644 index 0000000..75d4218 Binary files /dev/null and b/circle_app/assets/images/base/icon_login.png differ diff --git a/circle_app/assets/images/mine/icon_play.png b/circle_app/assets/images/mine/icon_play.png new file mode 100644 index 0000000..7df0ddb Binary files /dev/null and b/circle_app/assets/images/mine/icon_play.png differ diff --git a/circle_app/lib/app/aboutapp/logic.dart b/circle_app/lib/app/aboutapp/logic.dart index 4ab86d9..d13ff7c 100644 --- a/circle_app/lib/app/aboutapp/logic.dart +++ b/circle_app/lib/app/aboutapp/logic.dart @@ -1,7 +1,34 @@ import 'package:get/get.dart'; +import '../../util/device.dart'; import 'state.dart'; +import 'package:package_info_plus/package_info_plus.dart'; class AboutappLogic extends GetxController { final AboutappState state = AboutappState(); + String version = ""; + @override + void onInit() { + // TODO: implement onInit + super.onInit(); + getVersion(); + // getAppVersion(); + + } + getVersion() async { + final info = await PackageInfo.fromPlatform(); + version = info.version; + update(); + return version; + } + + + Future getAppVersion() async { + final info = await PackageInfo.fromPlatform(); + print(info.appName); + print(info.packageName); + print(info.version); + print(info.buildNumber); + + } } diff --git a/circle_app/lib/app/aboutapp/state.dart b/circle_app/lib/app/aboutapp/state.dart index ef106da..7bc6c49 100644 --- a/circle_app/lib/app/aboutapp/state.dart +++ b/circle_app/lib/app/aboutapp/state.dart @@ -2,4 +2,5 @@ class AboutappState { AboutappState() { ///Initialize variables } + } diff --git a/circle_app/lib/app/aboutapp/view.dart b/circle_app/lib/app/aboutapp/view.dart index 6e35036..967a118 100644 --- a/circle_app/lib/app/aboutapp/view.dart +++ b/circle_app/lib/app/aboutapp/view.dart @@ -41,12 +41,12 @@ class AboutappPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ - // Image.asset( - // getHomeImage("mine_circle"), // Replace with your image path - // width: double.infinity, - // height: double.infinity, - // fit: BoxFit.contain, - // ), + Image.asset( + getBaseImage("icon_login"), // Replace with your image path + width: 100.sp, + height: 100.sp, + fit: BoxFit.contain, + ), SizedBox(height: 20.sp), Text( '圈子', @@ -161,7 +161,7 @@ class AboutappPage extends StatelessWidget { ), ), Text( - '1.0.0', + logic.version, style: TextStyle( color: Color(0xFFB7BECC), fontSize: 12.sp, diff --git a/circle_app/lib/app/call_out/logic.dart b/circle_app/lib/app/call_out/logic.dart index c3ae4ef..52aa99d 100644 --- a/circle_app/lib/app/call_out/logic.dart +++ b/circle_app/lib/app/call_out/logic.dart @@ -1,4 +1,6 @@ +import 'dart:async'; import 'dart:io'; +import 'dart:typed_data'; import 'package:circle_app/util/util.dart'; import 'package:flutter/cupertino.dart'; @@ -6,6 +8,8 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:qiniu_flutter_sdk/qiniu_flutter_sdk.dart'; +import 'package:video_player/video_player.dart'; +import 'package:video_thumbnail/video_thumbnail.dart'; import '../../network/api.dart'; import '../../network/dio_manager.dart'; @@ -13,6 +17,7 @@ import '../../router/app_routers.dart'; import '../login/complete_material/logic.dart'; import '../select_circle/logic.dart'; import 'state.dart'; +import '../../common/config.dart'; class Call_outLogic extends GetxController { final Call_outState state = Call_outState(); @@ -23,10 +28,24 @@ class Call_outLogic extends GetxController { final ImagePicker _picker = ImagePicker(); var storage = Storage(); var quToken = ''; + VideoPlayerController? videoPlayerController; + List numbers = []; @override - void onInit() async{ + void onClose() { + super.onClose(); + videoPlayerController?.dispose(); + } + + @override + void dispose() { + videoPlayerController?.dispose(); + super.dispose(); + } + + @override + void onInit() async { super.onInit(); var data = await DioManager.instance.get(url: Api.getCircleList, params: {}); @@ -34,24 +53,66 @@ class Call_outLogic extends GetxController { data, (data) => ConfigBean.fromJson(data)); configBean = bean.data!; - - - var quniuData = await DioManager.instance.get(url: Api.getqiniuToken, params: {}); + var quniuData = + await DioManager.instance.get(url: Api.getqiniuToken, params: {}); var qiniuBean = BaseResponse.fromJson( quniuData, (quniuData) => QnTokenData.fromJson(quniuData)); quToken = qiniuBean.data!.token.toString(); - - } - List numbers = []; + + sendShout() async { + if (numbers.isEmpty) { + showToast("选择圈子"); + return; + } + if (textEditingController.text.isEmpty) { + showToast("请输入喊话内容"); + return; + } + if (state.imaglist.isEmpty || state.videolist.isEmpty) { + if (textEditingController.text.length < 50) { + showToast("内容不丰富"); + return; + } + } else { + if (!state.imaglist.isEmpty) { + if (textEditingController.text.length < 10) { + showToast("内容不丰富"); + return; + } + } + if (!state.videolist.isEmpty) { + if (textEditingController.text.length < 10) { + showToast("内容不丰富"); + return; + } + } + } + + List myBean = []; + if (!state.imaglist.isEmpty){ + state.imaglist.forEach((element) { + myBean.add(MyBean(type: 1, url: element).toJson()); + }); + } + if (!state.videolist.isEmpty){ + myBean.add(MyBean(type: 1, url: state.videolist[0]).toJson()); + } +print(myBean.toString()); + var data = await DioManager.instance.post(url: Api.SendShout, params: { + 'album': myBean, + 'content': textEditingController.text, + 'interest_id': numbers[0].id, + 'useQueen': isCheck, + }); + + //Navigator.pop(context, numbers); + } + startSelectCircleActivity() async { - var data = await Get.toNamed(AppRoutes.SelectCircleActivity, - arguments: { - "interestMap": - configBean.interestMap, - "isRodio": true - }); - if(null!=data){ + var data = await Get.toNamed(AppRoutes.SelectCircleActivity, + arguments: {"interestMap": configBean.interestMap, "isRodio": true}); + if (null != data) { numbers = data; circleName = numbers[0].name; @@ -59,30 +120,56 @@ class Call_outLogic extends GetxController { update(); } } + showImg() async { try { - if(state.imaglist.length==9){ - showToast("最多上传9张图片哦~"); + if (state.videolist.isNotEmpty) { + showToast("已添加图片,无法添加图片。"); return; } - final XFile? pickedFile = await _picker.pickImage(source: ImageSource.gallery,); - // setState(() { + if (state.imaglist.length == 6) { + showToast("最多上传6张图片哦~"); + return; + } + final XFile? pickedFile = await _picker.pickImage( + source: ImageSource.gallery, + ); _setImageFileListFromFile(pickedFile!); - // }); } catch (e) { print(e); - // setState(() { - // _pickImageError = e; - // }); } } + Future getFirstPic(url) async { + Uint8List? bytes = await VideoThumbnail.thumbnailData(video: url); + final Completer completer = Completer(); + if (bytes != null) { + int _imageDataSize = bytes.length; + print("image size: $_imageDataSize"); + + final _image = Image.memory(bytes); + _image.image + .resolve(ImageConfiguration()) + .addListener(ImageStreamListener((ImageInfo info, bool _) { + completer.complete(ThumbnailResult( + image: _image, + dataSize: _imageDataSize, + height: info.image.height, + width: info.image.width, + )); + })); + } + + return completer.future; + } + void _setImageFileListFromFile(XFile pickedFile) { SmartDialog.showLoading(); + String imgPath = CONFIG.CALL_OUT_IMAGE + pickedFile.name; PutController putController = PutController(); putController.addStatusListener((StorageStatus status) { if (status == StorageStatus.Success) { - var headUrl = "http://qiniuyun.ikuayou.com/" + pickedFile.name; + var headUrl = CONFIG.IMAGE_HEAD + imgPath; state.imaglist.add(headUrl); update(); @@ -91,28 +178,113 @@ class Call_outLogic extends GetxController { print('状态变化: 当前任务状态:$status'); }); storage.putFile(File(pickedFile.path), quToken, - options: PutOptions(controller: putController, key: pickedFile.name)); + options: PutOptions( + controller: putController, + key: imgPath)); } + showVideo() async { - if(state.imaglist.length!=0){ - showToast("不可以和图片一起上传哦~"); + if (state.imaglist.length != 0) { + showToast("已添加图片,无法添加视频。"); + return; + } + if (state.videolist.length == 6) { + showToast("最多上传6个视频哦~"); return; } try { final XFile? pickedFile = await _picker.pickVideo( source: ImageSource.gallery, ); - // setState(() { - _setImageFileListFromFile(pickedFile!); - // }); - } catch (e) { - // setState(() { - // _pickImageError = e; - // }); - } + print(pickedFile!.path.toString()); + videoPlayerController = VideoPlayerController.file( + File(pickedFile!.path), + videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true), + ); + await videoPlayerController?.initialize(); + final Duration videoDuration = videoPlayerController!.value.duration; + final double durationInSeconds = videoDuration.inSeconds.toDouble(); + print(durationInSeconds.toString()); + if (durationInSeconds >= 5 && durationInSeconds <= 30) { + videoPlayerController?.setLooping(true); + videoPlayerController?.addListener(() { + if (!videoPlayerController!.value.isPlaying) { + // Navigator.pop(context); + } + }); + + _setVideoFileListFromFile(pickedFile!); + }else{ + showToast("请上传5-30秒的视频"); + } + + } catch (e) {} } + void _setVideoFileListFromFile(XFile pickedFile) { + SmartDialog.showLoading(); + String videoPath = CONFIG.CALL_OUT_VIDEO + pickedFile.name; + PutController putController = PutController(); + putController.addStatusListener((StorageStatus status) async { + print('状态变化: 当前任务状态:$status'); + if (status == StorageStatus.Success) { + // var img = await getFirstPic(CONFIG.IMAGE_HEAD + pickedFile.name); + state.videolist.add(CONFIG.IMAGE_HEAD + videoPath); + //state.videoThumbnaillist =img; + print(CONFIG.IMAGE_HEAD + videoPath); + + + update(); + SmartDialog.dismiss(); + } + }); + storage.putFile(File(pickedFile.path), quToken, + options: PutOptions( + controller: putController, + key: CONFIG.CALL_OUT_VIDEO + pickedFile.name)); + } + + Future _loadCaptions(BuildContext context) async { + final String fileContents = await DefaultAssetBundle.of(context) + .loadString('assets/bumble_bee_captions.vtt'); + return WebVTTCaptionFile( + fileContents); // For vtt files, use WebVTTCaptionFile + } +} + +class MyBean { + int type; + String url; + + MyBean({required this.type, required this.url}); + + factory MyBean.fromJson(Map json) { + return MyBean( + type: json['type'], + url: json['url'], + ); + } + + Map toJson() { + return { + 'type': type, + 'url': url, + }; + } +} + +class ThumbnailResult { + final Image image; + final int dataSize; + final int height; + final int width; + + const ThumbnailResult( + {required this.image, + required this.dataSize, + required this.height, + required this.width}); } diff --git a/circle_app/lib/app/call_out/state.dart b/circle_app/lib/app/call_out/state.dart index 4db8ab8..91bd948 100644 --- a/circle_app/lib/app/call_out/state.dart +++ b/circle_app/lib/app/call_out/state.dart @@ -1,13 +1,10 @@ +import 'logic.dart'; + class Call_outState { Call_outState() { ///Initialize variables } - List imaglist = ["https://book.flutterchina.club/assets/img/logo.png", - "https://book.flutterchina.club/assets/img/logo.png", - "https://book.flutterchina.club/assets/img/logo.png", - "https://book.flutterchina.club/assets/img/logo.png", - "https://book.flutterchina.club/assets/img/logo.png", - "https://book.flutterchina.club/assets/img/logo.png",]; - + List imaglist = []; + List videolist = []; } diff --git a/circle_app/lib/app/call_out/view.dart b/circle_app/lib/app/call_out/view.dart index 3409575..d742299 100644 --- a/circle_app/lib/app/call_out/view.dart +++ b/circle_app/lib/app/call_out/view.dart @@ -3,6 +3,7 @@ import 'package:circle_app/util/util.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:video_player/video_player.dart'; import '../../router/app_routers.dart'; import 'logic.dart'; @@ -36,7 +37,9 @@ class Call_outPage extends StatelessWidget { width: 54.sp, ), onPressed: () { - showToast('111'); + // + //showToast('111'); + logic.sendShout(); }, ), body: SafeArea( @@ -117,7 +120,8 @@ class Call_outPage extends StatelessWidget { maxLength: 200, decoration: InputDecoration( hintStyle: TextStyle( - color: Color.fromRGBO(255, 255, 255, 0.6), + color: Color.fromRGBO( + 255, 255, 255, 0.6), fontSize: 14.sp), hintText: '请输入...(左下角上传图片或视频哦)', border: InputBorder.none, @@ -128,16 +132,19 @@ class Call_outPage extends StatelessWidget { ), Positioned( right: 15.sp, - top: 190.sp, + top: 190.sp, child: Text( '${controller.textEditingController.text.length}/200', style: TextStyle( color: Colors.white, fontSize: 12.sp), )), + Container( + margin: EdgeInsets.only(top: 220.sp), + child: _imageAdapter(controller)), + Container( + margin: EdgeInsets.only(top: 220.sp,left: 15.sp,right: 15.sp), - Container( - margin: EdgeInsets.only(top: 220.sp), - child: _imageAdapter(controller)) + child:_showVideo(controller) ,) ], ), @@ -216,8 +223,56 @@ class Call_outPage extends StatelessWidget { )), ); }); - } + + Widget _showVideo(Call_outLogic controller) { + if (controller.videoPlayerController == null) { + return Container(); + } else { + return Container( + width:controller.videoPlayerController!.value.size.width < controller.videoPlayerController!.value.size.height ? 135.sp : 240.sp, + height:controller.videoPlayerController!.value.size.width < controller.videoPlayerController!.value.size.height ? 240.sp :135.sp, + child: GestureDetector( + onTap: () { + if(controller.videoPlayerController!.value.isPlaying){ + controller.videoPlayerController!.pause(); + }else{ + controller.videoPlayerController!.play(); + } + controller.update(); + }, + child: AspectRatio( + aspectRatio: controller.videoPlayerController!.value.aspectRatio, + child: Stack( + children: [ + VideoPlayer(controller.videoPlayerController!), + Center(child:controller.videoPlayerController!.value.isPlaying ? Container() : Image(image: AssetImage(getMineImage("icon_play")),width: 30.sp,height: 30.sp,),), + Positioned( + top: 0, + right: 0, + child: GestureDetector( + onTap: () { + // showToast("删除"); + _showDelVideoDialog(Get.context!, controller); + }, + child: Image( + image: AssetImage(getMineImage("icon_img_del")), + width: 20.sp, + height: 20.sp, + ), + )) + + // ClosedCaption(text: controller.videoPlayerController!.value.caption.text), + // _ControlsOverlay(controller: controller.videoPlayerController), + // VideoProgressIndicator(controller.videoPlayerController!, allowScrubbing: true), + ], + ), + ), + ), + ); + } + } + Widget _imageAdapter(Call_outLogic controller) { return GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( @@ -225,18 +280,17 @@ class Call_outPage extends StatelessWidget { ), itemCount: controller.state.imaglist.length, // 项目的总数量,包括固定图片和接口获取的项目 itemBuilder: (BuildContext context, int index) { - return Container( - margin: EdgeInsets.all(5.sp), - child: Center( - child: _buildImageItem( - controller.state.imaglist[index], - controller,index)), - ); - + return Container( + margin: EdgeInsets.all(5.sp), + child: Center( + child: _buildImageItem( + controller.state.imaglist[index], controller, index)), + ); }, ); } - Widget _buildImageItem(String url, Call_outLogic controller,int index) { + + Widget _buildImageItem(String url, Call_outLogic controller, int index) { return Stack( children: [ ClipRRect( @@ -249,8 +303,8 @@ class Call_outPage extends StatelessWidget { child: GestureDetector( onTap: () { Get.toNamed(AppRoutes.Swiper, arguments: { - 'imaglist':controller.state.imaglist, - 'index':index + 'imaglist': controller.state.imaglist, + 'index': index }); }, child: Image.network( @@ -259,28 +313,170 @@ class Call_outPage extends StatelessWidget { ), ), ), - ) - , + ), ), - Positioned( - top: 0, - right: 0, - child: GestureDetector( - onTap: () { - // showToast("删除"); - _showDelImgDialog(Get.context!,controller,index); - - }, - child: Image( - image: AssetImage(getMineImage("icon_img_del")), - width: 20.sp, - height: 20.sp, - ), - )) + Positioned( + top: 0, + right: 0, + child: GestureDetector( + onTap: () { + // showToast("删除"); + _showDelImgDialog(Get.context!, controller, index); + }, + child: Image( + image: AssetImage(getMineImage("icon_img_del")), + width: 20.sp, + height: 20.sp, + ), + )) ], ); } - void _showDelImgDialog(BuildContext context,Call_outLogic controller,int index) { + + void _showDelImgDialog( + BuildContext context, Call_outLogic controller, int index) { + showDialog( + context: context, + builder: (BuildContext context) { + return Dialog( + backgroundColor: Colors.transparent, + child: Container( + height: 160.sp, + padding: EdgeInsets.all(1.0), + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(10.0), + gradient: LinearGradient( + colors: [Color(0xFFDD3DF4), Color(0xFF30FFD9)], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + ), + Container( + margin: EdgeInsets.all(1.sp), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(10.0), + gradient: LinearGradient( + colors: [Color(0xFF4C3E5F), Color(0xFF324140)], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + ), + Container( + margin: EdgeInsets.only(top: 24.sp), + child: Column( + children: [ + Center( + child: Text( + "提示", + style: + TextStyle(color: Colors.white, fontSize: 16.sp), + ), + ), + Container( + margin: EdgeInsets.only( + top: 12.sp, left: 14.sp, right: 14.sp), + alignment: Alignment.center, + child: Text( + "是否确认删除该照片。", + textAlign: TextAlign.center, + style: TextStyle( + color: Color(0xCCF7FAFA), fontSize: 16.sp), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Container( + margin: EdgeInsets.only(top: 30.sp), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(17), + gradient: LinearGradient( + colors: [ + Color(0x26FFFFFF), + Color(0x26FFFFFF), + ], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + ), + padding: EdgeInsets.only( + top: 10.sp, + bottom: 10.sp, + left: 52.sp, + right: 52.sp), + child: Text( + "否", + style: TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), + ), + ), + SizedBox(width: 24.sp), + GestureDetector( + onTap: () { + Navigator.pop(context); + controller.state.imaglist.removeAt(index); + controller.update(); + }, + child: Container( + margin: EdgeInsets.only(top: 24.sp), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(17), + gradient: LinearGradient( + colors: [ + Color(0xFF06F9FA), + Color(0xFFDC5BFD), + ], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + ), + padding: EdgeInsets.only( + top: 10.sp, + bottom: 10.sp, + left: 52.sp, + right: 52.sp), + child: Text( + "是", + style: TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), + ), + ) + ], + ) + ], + ), + ) + ], + ), + ), + ); + }, + ); + } + + + + + void _showDelVideoDialog( + BuildContext context, Call_outLogic controller) { showDialog( context: context, builder: (BuildContext context) { @@ -330,7 +526,7 @@ class Call_outPage extends StatelessWidget { top: 12.sp, left: 14.sp, right: 14.sp), alignment: Alignment.center, child: Text( - "是否确认删除该形象照。", + "是否确认删除该视频。", textAlign: TextAlign.center, style: TextStyle( color: Color(0xCCF7FAFA), fontSize: 16.sp), @@ -375,9 +571,8 @@ class Call_outPage extends StatelessWidget { GestureDetector( onTap: () { Navigator.pop(context); - controller.state.imaglist.removeAt(index); + controller.videoPlayerController=null; controller.update(); - }, child: Container( margin: EdgeInsets.only(top: 24.sp), diff --git a/circle_app/lib/app/circle/logic.dart b/circle_app/lib/app/circle/logic.dart index 8011a75..01496dd 100644 --- a/circle_app/lib/app/circle/logic.dart +++ b/circle_app/lib/app/circle/logic.dart @@ -7,7 +7,8 @@ import '../../network/dio_manager.dart'; import 'state.dart'; class CircleLogic extends GetxController { - PageController pageController = PageController(initialPage: 1, viewportFraction: 0.8); + PageController pageController = + PageController(initialPage: 1, viewportFraction: 0.8); InterestsBean circle = InterestsBean(lists: []); final CircleState state = CircleState(); int page = 1; @@ -33,19 +34,24 @@ class CircleLogic extends GetxController { update(); } - - outCircle(String interest_id,bool isStatus) async{ - var data = await DioManager.instance.post(url: Api.outCrrcle+interest_id+"/join", params: {"status": isStatus?"0":"1"}); + outCircle(String interest_id, bool isStatus) async { + var data = await DioManager.instance.post( + url: Api.outCrrcle + interest_id + "/join", + params: {"status": isStatus ? "0" : "1"}); var bean = BaseResponse.fromJson(data, (data) => data); if (bean.code == 200) { circle.lists.forEach((element) { - if(element.id.toString()==interest_id.toString()){ + if (element.id.toString() == interest_id.toString()) { element.isJoin = !isStatus; } }); } showToast(bean.msg); } + + getCircleIndexId() { + return circle.lists[state.index].id; + } } class InterestsBean { diff --git a/circle_app/lib/app/circle/view.dart b/circle_app/lib/app/circle/view.dart index df18421..fa797e9 100644 --- a/circle_app/lib/app/circle/view.dart +++ b/circle_app/lib/app/circle/view.dart @@ -284,4 +284,202 @@ class _CirclePageState extends State ); } + void _showTextContentDialog(BuildContext context, String msg) { + showDialog( + context: context, + builder: (BuildContext context) { + return Dialog( + backgroundColor: Colors.transparent, + child: Container( + height: 300.sp, + padding: EdgeInsets.all(1.0), + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(10.0), + gradient: LinearGradient( + colors: [Color(0xFFDD3DF4), Color(0xFF30FFD9)], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + ), + Container( + margin: EdgeInsets.all(1.sp), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(10.0), + gradient: LinearGradient( + colors: [Color(0xFF4C3E5F), Color(0xFF324140)], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + ), + Container( + margin: EdgeInsets.only(top: 24.sp), + child: Column( + children: [ + Container( + margin: EdgeInsets.only( + top: 12.sp, left: 14.sp, right: 14.sp), + alignment: Alignment.center, + child: Text( + msg, + textAlign: TextAlign.center, + style: TextStyle( + color: Color(0xCCF7FAFA), fontSize: 16.sp), + ), + ), + ], + ), + ) + ], + ), + ), + ); + }, + ); + } + + void _showOutCircleDialog( + BuildContext context, CircleLogic controller, Circle bean) { + showDialog( + context: context, + builder: (BuildContext context) { + return Dialog( + backgroundColor: Colors.transparent, + child: Container( + height: 160.sp, + padding: EdgeInsets.all(1.0), + child: Stack( + children: [ + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(10.0), + gradient: LinearGradient( + colors: [Color(0xFFDD3DF4), Color(0xFF30FFD9)], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + ), + Container( + margin: EdgeInsets.all(1.sp), + decoration: BoxDecoration( + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(10.0), + gradient: LinearGradient( + colors: [Color(0xFF4C3E5F), Color(0xFF324140)], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), + ), + ), + Container( + margin: EdgeInsets.only(top: 24.sp), + child: Column( + children: [ + Center( + child: Text( + "提示", + style: + TextStyle(color: Colors.white, fontSize: 16.sp), + ), + ), + Container( + margin: EdgeInsets.only( + top: 12.sp, left: 14.sp, right: 14.sp), + alignment: Alignment.center, + child: Text( + "是否确认退出该圈子。", + textAlign: TextAlign.center, + style: TextStyle( + color: Color(0xCCF7FAFA), fontSize: 16.sp), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Container( + margin: EdgeInsets.only(top: 30.sp), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(17), + gradient: LinearGradient( + colors: [ + Color(0x26FFFFFF), + Color(0x26FFFFFF), + ], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + ), + padding: EdgeInsets.only( + top: 10.sp, + bottom: 10.sp, + left: 52.sp, + right: 52.sp), + child: Text( + "否", + style: TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), + ), + ), + SizedBox(width: 24.sp), + GestureDetector( + onTap: () { + Navigator.pop(context); + logic.outCircle(bean.id.toString(), bean.isJoin); + }, + child: Container( + margin: EdgeInsets.only(top: 24.sp), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(17), + gradient: LinearGradient( + colors: [ + Color(0xFF06F9FA), + Color(0xFFDC5BFD), + ], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + ), + padding: EdgeInsets.only( + top: 10.sp, + bottom: 10.sp, + left: 52.sp, + right: 52.sp), + child: Text( + "是", + style: TextStyle( + color: Colors.white, + fontSize: 12, + ), + ), + ), + ) + ], + ) + ], + ), + ) + ], + ), + ), + ); + }, + ); + } + } diff --git a/circle_app/lib/app/feedback/logic.dart b/circle_app/lib/app/feedback/logic.dart index fecdada..16869ec 100644 --- a/circle_app/lib/app/feedback/logic.dart +++ b/circle_app/lib/app/feedback/logic.dart @@ -33,6 +33,7 @@ class FeedbackLogic extends GetxController { putController.addStatusListener((StorageStatus status) { print('状态变化: 当前任务状态:$status'); }); - storage.putFile(File(pickedFile.path), "",options: PutOptions(controller: putController)); + // storage.putFile(File(pickedFile.path), quToken, + // options: PutOptions(controller: putController, key: CONFIG.USER_INFO_HEAD+pickedFile.name)); } } diff --git a/circle_app/lib/app/login/complete_material/logic.dart b/circle_app/lib/app/login/complete_material/logic.dart index 5f8758b..2bd9396 100644 --- a/circle_app/lib/app/login/complete_material/logic.dart +++ b/circle_app/lib/app/login/complete_material/logic.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'dart:math'; import 'package:circle_app/network/dio_manager.dart'; import 'package:circle_app/router/app_routers.dart'; @@ -9,6 +10,7 @@ import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:qiniu_flutter_sdk/qiniu_flutter_sdk.dart'; +import '../../../common/config.dart'; import '../../../network/api.dart'; import '../../../util/device.dart'; import '../../select_circle/logic.dart'; @@ -79,7 +81,7 @@ class Complete_materialLogic extends GetxController { PutController putController = PutController(); putController.addStatusListener((StorageStatus status) { if (status == StorageStatus.Success) { - headUrl = "http://qiniuyun.ikuayou.com/" + pickedFile.name; + headUrl = CONFIG.IMAGE_HEAD + pickedFile.name; print(headUrl); update(); SmartDialog.dismiss(); @@ -87,7 +89,7 @@ class Complete_materialLogic extends GetxController { print('状态变化: 当前任务状态:$status'); }); storage.putFile(File(pickedFile.path), quToken, - options: PutOptions(controller: putController, key: pickedFile.name)); + options: PutOptions(controller: putController, key: CONFIG.USER_INFO_AVATAR+pickedFile.name)); } checkInfo() async { @@ -143,6 +145,8 @@ class Complete_materialLogic extends GetxController { var bean = BaseResponse.fromJson(data, (data) => data); if (bean.code == 200) { Get.offAllNamed(AppRoutes.Home); + }else{ + showToast(bean.msg); } } diff --git a/circle_app/lib/app/setup/logic.dart b/circle_app/lib/app/setup/logic.dart index b64326f..3f1a595 100644 --- a/circle_app/lib/app/setup/logic.dart +++ b/circle_app/lib/app/setup/logic.dart @@ -1,7 +1,38 @@ import 'package:get/get.dart'; +import '../../util/CacheUtil.dart'; import 'state.dart'; class SetupLogic extends GetxController { final SetupState state = SetupState(); + + String cache = ""; + + @override + void onInit() async { + super.onInit(); + + // + } + + @override + void onReady() async { + // TODO: implement onReady + super.onReady(); + getCache(); + } + + getCache() async { + cache = await CacheUtil.loadCache(); + print(cache); + update(); + } + + startCaching() async { + CacheUtil.clearCache((result) { + cache = result; + update(); + }); + + } } diff --git a/circle_app/lib/app/setup/view.dart b/circle_app/lib/app/setup/view.dart index 4b8e3b6..e3236a5 100644 --- a/circle_app/lib/app/setup/view.dart +++ b/circle_app/lib/app/setup/view.dart @@ -1,4 +1,3 @@ - import 'package:circle_app/components/my_app_bar.dart'; import 'package:circle_app/util/util.dart'; import 'package:flutter/material.dart'; @@ -14,95 +13,103 @@ import 'logic.dart'; class SetupPage extends StatelessWidget { SetupPage({Key? key}) : super(key: key); - final logic = Get.find(); - final state = Get.find().state; @override Widget build(BuildContext context) { - // _getFormat(context); - return Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage(getBaseImage("home_back")), - fit: BoxFit.cover, + // _getFormat(context); + return GetBuilder(builder: (logic) { + return Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage(getBaseImage("home_back")), + fit: BoxFit.cover, + ), ), - ), - child: Scaffold( - backgroundColor: Colors.transparent, - appBar: MyAppBar(centerTitle: '设置',), - body: SafeArea( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: MyAppBar(centerTitle: '设置',), + body: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - // GestureDetector( - // onTap: () { - // - // }, - // child: Image.asset( - // getNavigatorImage("back"), // 将 @mipmap/icon_back 替换为相应的图像路径 - // width: 24, // 将 @dimen/dp_24 替换为相应的值 - // height: 24, // 将 @dimen/dp_24 替换为相应的值 - // ), - // ), - // Spacer(), - // Text( - // '设置', - // style: TextStyle( - // color: Color(0xFFF7FAFA), // 将 #fff7fafa 替换为相应的颜色值 - // fontSize: 18.sp, // 将 18sp 替换为相应的值 - // ), - // ), - // Spacer(), + Row( + children: [ + // GestureDetector( + // onTap: () { + // + // }, + // child: Image.asset( + // getNavigatorImage("back"), // 将 @mipmap/icon_back 替换为相应的图像路径 + // width: 24, // 将 @dimen/dp_24 替换为相应的值 + // height: 24, // 将 @dimen/dp_24 替换为相应的值 + // ), + // ), + // Spacer(), + // Text( + // '设置', + // style: TextStyle( + // color: Color(0xFFF7FAFA), // 将 #fff7fafa 替换为相应的颜色值 + // fontSize: 18.sp, // 将 18sp 替换为相应的值 + // ), + // ), + // Spacer(), + ], + ), + SizedBox(height: 16.sp), // 将 @dimen/dp_16 替换为相应的值 + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Get.toNamed(AppRoutes.AccountActivity); + // controller.state.hearUrl + + }, + child: _buildItemRow('账号中心', getHomeImage("icon_in")), + ), + + SizedBox(height: 16.sp), + // _buildItemRow('隐私设置', getHomeImage("icon_in")), + // SizedBox(height: 16.sp), + // _buildItemRow('聊天设置', getHomeImage("icon_in")), + // SizedBox(height: 16.sp), + + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Get.toNamed(AppRoutes.BlackActivity); + }, + child: _buildItemRow('黑名单', getHomeImage("icon_in")), + ), + SizedBox(height: 16.sp), + // _buildItemRow('系统权限管理', getHomeImage("icon_in")), + // SizedBox(height: 16.sp), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + logic.startCaching(); + }, + child: _buildCacheItemRow('清除缓存', getHomeImage("icon_in"), context, logic), + ), + + SizedBox(height: 16.sp), + + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + Get.toNamed(AppRoutes.AboutAppActivity); + }, + child: _buildItemRow('关于圈子', getHomeImage("icon_in")), + ), ], ), - SizedBox(height: 16.sp), // 将 @dimen/dp_16 替换为相应的值 - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () { - Get.toNamed(AppRoutes.AccountActivity); - // controller.state.hearUrl - - }, - child: _buildItemRow('账号中心', getHomeImage("icon_in")), - ), - - SizedBox(height: 16.sp), - // _buildItemRow('隐私设置', getHomeImage("icon_in")), - // SizedBox(height: 16.sp), - // _buildItemRow('聊天设置', getHomeImage("icon_in")), - // SizedBox(height: 16.sp), - - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () { - Get.toNamed(AppRoutes.BlackActivity); - }, - child: _buildItemRow('黑名单', getHomeImage("icon_in")), - ), - SizedBox(height: 16.sp), - // _buildItemRow('系统权限管理', getHomeImage("icon_in")), - // SizedBox(height: 16.sp), - _buildCacheItemRow('清除缓存', getHomeImage("icon_in"),context), - SizedBox(height: 16.sp), - - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () { - Get.toNamed(AppRoutes.AboutAppActivity); - }, - child: _buildItemRow('关于圈子', getHomeImage("icon_in")), - ), - ], - ), - ),), - ); + ),), + ); + }); } Widget _buildItemRow(String text, String imagePath) { return Container( - padding: EdgeInsets.symmetric(horizontal: 16.sp), // 将 @dimen/dp_16 替换为相应的值 + padding: EdgeInsets.symmetric(horizontal: 16.sp), + // 将 @dimen/dp_16 替换为相应的值 child: Row( children: [ Text( @@ -123,9 +130,11 @@ class SetupPage extends StatelessWidget { ); } - Widget _buildCacheItemRow(String text, String imagePath,BuildContext context) { + Widget _buildCacheItemRow(String text, String imagePath, BuildContext context, + SetupLogic logic) { return Container( - padding: EdgeInsets.symmetric(horizontal: 16.sp), // 将 @dimen/dp_16 替换为相应的值 + padding: EdgeInsets.symmetric(horizontal: 16.sp), + // 将 @dimen/dp_16 替换为相应的值 child: Row( children: [ Text( @@ -136,9 +145,9 @@ class SetupPage extends StatelessWidget { ), ), Spacer(), - // _getFormat(context), + // _getFormat(context), Text( - 'XXX', // 将 'XXX' 替换为相应的缓存大小值 + logic.cache, // 将 'XXX' 替换为相应的缓存大小值 style: TextStyle( color: Color(0xFFB7BECC), // 将 #ffb7becc 替换为相应的颜色值 fontSize: 14.sp, // 将 14sp 替换为相应的值 @@ -156,6 +165,4 @@ class SetupPage extends StatelessWidget { } - - } \ No newline at end of file diff --git a/circle_app/lib/app/splash/logic.dart b/circle_app/lib/app/splash/logic.dart index 8203839..c17d69c 100644 --- a/circle_app/lib/app/splash/logic.dart +++ b/circle_app/lib/app/splash/logic.dart @@ -34,7 +34,10 @@ class SplashLogic extends GetxController { return; } showToast(bean.msg.toString()); - + if(bean.code == 500){ + await Future.delayed(Duration(seconds: 5)); + onInit(); + } diff --git a/circle_app/lib/app/util/device.dart b/circle_app/lib/app/util/device.dart new file mode 100644 index 0000000..b9f78bb --- /dev/null +++ b/circle_app/lib/app/util/device.dart @@ -0,0 +1 @@ +// TODO Implement this library. \ No newline at end of file diff --git a/circle_app/lib/common/config.dart b/circle_app/lib/common/config.dart new file mode 100644 index 0000000..90a71ba --- /dev/null +++ b/circle_app/lib/common/config.dart @@ -0,0 +1,10 @@ +class CONFIG{ + static const IMAGE_HEAD = 'http://qiniuyun.ikuayou.com/'; + + + static const CALL_OUT_VIDEO = 'call_out_video/'; + + static const CALL_OUT_IMAGE = 'call_out_image/'; + + static const USER_INFO_AVATAR = 'user_info_avatar/'; +} \ No newline at end of file diff --git a/circle_app/lib/network/api.dart b/circle_app/lib/network/api.dart index da857b9..d5e068c 100644 --- a/circle_app/lib/network/api.dart +++ b/circle_app/lib/network/api.dart @@ -37,4 +37,8 @@ class Api { //入圈出圈 static const outCrrcle = 'up-service/interest/'; + + + //发布喊话 + static const SendShout = 'up-service/callout'; } \ No newline at end of file diff --git a/circle_app/lib/network/dio_manager.dart b/circle_app/lib/network/dio_manager.dart index fbab001..3e16868 100644 --- a/circle_app/lib/network/dio_manager.dart +++ b/circle_app/lib/network/dio_manager.dart @@ -130,7 +130,9 @@ class DioManager { Options options = Options( method: methodValues[method], headers: { "Authorization": await getAuthorization(), - 'version': await getDeviceId(), + 'versionName': await getVersionName(), + 'versionCode': await getVersionCode(), + 'osVersion': await getDeviceId(), 'platform': Platform.isIOS ? '1' : '0', 'imei': await getImei(), 'brand': await getBrand(), diff --git a/circle_app/lib/util/CacheUtil.dart b/circle_app/lib/util/CacheUtil.dart new file mode 100644 index 0000000..69ad037 --- /dev/null +++ b/circle_app/lib/util/CacheUtil.dart @@ -0,0 +1,104 @@ +import 'dart:io'; +import 'package:circle_app/util/util.dart'; +import 'package:get/get.dart'; +import 'package:path_provider/path_provider.dart'; + +class CacheUtil { + static dynamic loadCache() async { + try { + final _tempDir = await getTemporaryDirectory(); + double value = await _getTotalSizeOfFilesInDir(_tempDir); + /*tempDir.list(followLinks: false,recursive: true).listen((file){ + //打印每个缓存文件的路径 + print(file.path); + });*/ + print('临时目录大小: ' + value.toString()); + return _renderSize(value); + } catch (err) { + print(err); + } + } + + ///递归方式删除目录 + static Future delDir(FileSystemEntity file) async { + try { + if (file is Directory) { + final List children = file.listSync(); + for (final FileSystemEntity child in children) { + await delDir(child); + } + } + await file.delete(); + } catch (e) { + print(e); + } + } + + static Future _getTotalSizeOfFilesInDir( + final FileSystemEntity file) async { + try { + if (file is File) { + int length = await file.length(); + return double.parse(length.toString()); + } + if (file is Directory) { + final List children = file.listSync(); + double total = 0; + if (children != null) + for (final FileSystemEntity child in children) + total += await _getTotalSizeOfFilesInDir(child); + return total; + } + return 0; + } catch (e) { + print(e); + return 0; + } + } + + ///格式化文件大小 + static _renderSize(double value) { + List unitArr = [] + ..add('B') + ..add('K') + ..add('M') + ..add('G'); + int index = 0; + while (value > 1024) { + index++; + value = value / 1024; + } + String size = value.toStringAsFixed(2); + return size + unitArr[index]; + } + + static clearCache(MyCallback callback) async { + //此处展示加载loading + try { + final _tempDir = await getTemporaryDirectory(); + double value = await _getTotalSizeOfFilesInDir(_tempDir); + print("$value"); + if (value.toInt() <= 0) { + showToast("暂无缓存"); + + // Get.back(); + } else if (value >= 0) { + // Get.back(); + showToast("正在清理中···"); + Future.delayed(Duration(seconds: 2), () async { + //删除缓存目录 + await delDir(_tempDir); + await loadCache(); + showToast("清理缓存成功"); + callback("0KB"); + }); + return "正在清理中···"; + } + } catch (e) { + print(e); + showToast("清除缓存失败"); + + } + } +} +typedef void MyCallback(String result); \ No newline at end of file diff --git a/circle_app/lib/util/device.dart b/circle_app/lib/util/device.dart index 43bba95..f596ed7 100644 --- a/circle_app/lib/util/device.dart +++ b/circle_app/lib/util/device.dart @@ -3,7 +3,8 @@ import 'dart:io'; import 'package:device_info/device_info.dart'; import 'package:geolocator/geolocator.dart'; import 'package:shared_preferences/shared_preferences.dart'; - +import 'package:package_info_plus/package_info_plus.dart'; +//手机系统版本 Future getDeviceId() async { String deviceId = ""; final DeviceInfoPlugin deviceInfoPlugin = new DeviceInfoPlugin(); @@ -23,6 +24,27 @@ Future getDeviceId() async { return deviceId; } + +Future getVersion() async { + String version = ""; + final info = await PackageInfo.fromPlatform(); + version = info.version; + return version; +} + +Future getVersionName() async { + String versionName = ""; + final info = await PackageInfo.fromPlatform(); + versionName = info.version; + return versionName; +} +Future getVersionCode() async { + String versionCode = ""; + final info = await PackageInfo.fromPlatform(); + versionCode = info.buildNumber; + return versionCode; +} +//imei Future getImei() async { String imei = ""; DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); @@ -37,7 +59,7 @@ Future getImei() async { } return imei; } - +//手机型号 Future getBrand() async { String brand = ''; DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); diff --git a/circle_app/pubspec.yaml b/circle_app/pubspec.yaml index cd1a222..9fc502f 100644 --- a/circle_app/pubspec.yaml +++ b/circle_app/pubspec.yaml @@ -68,8 +68,16 @@ dependencies: permission_handler: ^10.3.0 #loading flutter_smart_dialog: 4.9.2 - #获取位置信息 + #获取位置信息 geolocator: ^9.0.2 + #获取视频第一帧 + video_thumbnail: ^0.5.3 + #获取应用程序信息 + package_info_plus: ^1.4.3+1 + #视频播放器 + video_player: ^2.6.1 + + dev_dependencies: flutter_test: