|
- import 'dart:async';
- import 'dart:ui';
-
- import 'package:agora_rtc_engine/agora_rtc_engine.dart';
- import 'package:cached_network_image/cached_network_image.dart';
- import 'package:chat/chat/gift_page.dart';
- import 'package:chat/data/UserData.dart';
- import 'package:chat/data/WebData.dart';
- import 'package:chat/data/constants.dart';
- import 'package:chat/generated/i18n.dart';
- import 'package:chat/models/UserInfo.dart';
- import 'package:chat/models/gift_item_model.dart';
- import 'package:chat/models/gift_select_provider.dart';
- import 'package:chat/models/money_change.dart';
- import 'package:chat/models/ref_name_provider.dart';
- import 'package:chat/r.dart';
- import 'package:chat/utils/ChargeMoney.dart';
- import 'package:chat/utils/CustomUI.dart';
- import 'package:chat/utils/HttpUtil.dart';
- import 'package:chat/utils/MessageMgr.dart';
- import 'package:chat/utils/TokenMgr.dart';
- import 'package:chat/utils/anim_effect_overlay.dart';
- import 'package:chat/utils/counter_overlay.dart';
- import 'package:chat/utils/msgHandler.dart';
- import 'package:chat/utils/screen.dart';
- import 'package:chat/utils/sound_util.dart';
- import 'package:chat/utils/sp_utils.dart';
- import 'package:dio/dio.dart';
- import 'package:flutter/material.dart';
- import 'package:oktoast/oktoast.dart';
- import 'package:provider/provider.dart';
-
- class AudioChatPage extends StatefulWidget {
- final UserInfo userInfo;
- final bool isReplay;
- final bool isTranslateButler;
- final Function translateButlerCloseCallBack;
- AudioChatPage({@required this.userInfo, this.isReplay = false, this.isTranslateButler=false,this.translateButlerCloseCallBack});
- @override
- _AudioChatPageState createState() => _AudioChatPageState();
- }
-
- class _AudioChatPageState extends State<AudioChatPage> {
- //是否启用扬声器
- bool speakPhone = false;
-
- int friendId;
-
- bool isReply; //是否应答模式
-
- bool isChating = false; //是否通话中
-
- //超时挂断
- Timer offTimer;
- Timer callingTimer;
-
- String channelName;
-
- //打赏礼物信息
- List<GiftItemModel> giftList;
- final _controller = new PageController();
-
- //礼物数量
- int curGiftValue = 1;
-
- bool isQuit = false;
-
- @override
- void initState() {
- super.initState();
-
- friendId = widget.userInfo.userId;
- isReply = widget.isReplay;
-
- MsgHandler.isAudioConnect = true;
-
- getGiftList();
- initAgoreSdk();
- getDefaultSetting();
- //事件监听回调
- setAgoreEventListener();
-
- //礼物打赏
- MessageMgr().on('Receive Gift', receiveGift);
-
- MessageMgr().on('AudioChat Failed', closeChat);
-
- MessageMgr().on('AudioChat State', refuseAnswer);
- }
-
- void getDefaultSetting() async {
- bool soundPlayMode =
- (await SPUtils.getBool(Constants.SOUND_PLAY_MODE)) ?? false;
- setState(() {
- speakPhone = soundPlayMode;
- });
- AgoraRtcEngine.setEnableSpeakerphone(speakPhone);
- }
-
- closeChat(args) {
- showToast(I18n.of(context).not_online);
- _onExit(context);
- }
-
- @override
- void didChangeDependencies() {
- super.didChangeDependencies();
- print('test didChangeDependencies');
- }
-
- refuseAnswer(args) {
- var fdId = args['fdId'];
- var isAnswer = args['isAnswer'];
- if (fdId == friendId && !isAnswer) {
- // showToast('对方暂时无法接听');
- _onExit(context);
- }
- }
-
- receiveGift(gift) {
- int giftId = gift.giftId;
- int amount = gift.giftAmount;
- int total = gift.money;
-
- print(DateTime.now());
-
- var giftModel = giftList[giftId - 1];
- print('收到礼物金额:$total');
- UserData().incomeMoney += total;
- //Provider.of<MoneyChangeProvider>(context, listen: false).addMoney(total);
- AnimEffect.showEffect(context, giftId);
- AnimEffect.showDashangEffect(context, false, amount, giftModel.name);
- }
-
- //本页面即将销毁
- @override
- void dispose() {
- _controller.dispose();
- MessageMgr().off('AudioChat State', refuseAnswer);
- MessageMgr().off('AudioChat Failed', closeChat);
- MessageMgr().off('Receive Gift', receiveGift);
- MsgHandler.isAudioConnect = false;
-
- offTimer?.cancel();
-
- callingTimer?.cancel();
- SoundUtils().stop();
- AgoraRtcEngine.leaveChannel();
- //sdk资源释放
- AgoraRtcEngine.destroy();
- super.dispose();
- }
-
- void initAgoreSdk() {
- //初始化引擎
- AgoraRtcEngine.create(Constants.Agore_appId);
- //设置视频为可用 启用音频模块
- AgoraRtcEngine.enableAudio();
- //每次需要原生视频都要调用_createRendererView
- if (!isReply) {
- int myId = UserData().basicInfo.userId;
-
- _createRendererView(myId);
- }
- }
-
- void getGiftList() async {
- Map data = {
- "userId": UserData().basicInfo.userId,
- };
- data['sign'] = TokenMgr().getSign(data);
-
- Response res = await HttpUtil().post('prop/get/list', data: data);
-
- if (res == null) {
- return;
- }
- print(res);
- Map resData = res.data;
-
- if (resData['code'] == 0) {
- //领取成功
- giftList = resData['data']
- .map<GiftItemModel>((v) => GiftItemModel.fromJson(v))
- .toList();
-
- print('giftList length : ${giftList.length}');
- }
- }
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- body: SafeArea(
- child: Stack(
- children: <Widget>[
- ConstrainedBox(
- constraints: BoxConstraints.expand(),
- child: CachedNetworkImage(
- imageUrl: widget.userInfo.headimgurl,
- fit: BoxFit.fill,
- placeholder: CustomUI.buildImgLoding)),
- BackdropFilter(
- filter: new ImageFilter.blur(
- sigmaX: Screen.width / 8, sigmaY: Screen.width / 8),
- child: Container(
- color: Colors.black.withOpacity(0.5),
- ),
- ),
- SafeArea(
- child: Padding(
- padding: EdgeInsets.symmetric(vertical: 40),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- _viewAudio(),
- isReply ? _replayToolBar() : _bottomToolBar(),
- ],
- ))),
- widget.isTranslateButler?InkWell(child: Container( width: 60,height: 60,child: Align(child: Icon(
- IconData(0xe67f, fontFamily: Constants.IconFontFamily),
- color: Colors.white,
- size: 28.0,
- ),alignment: Alignment.center,),),onTap: (){
- widget.translateButlerCloseCallBack(1);
- print('内页内页');
- },):Container()
- ],
- )));
- }
-
- _viewAudio() {
- var url = widget.userInfo.headimgurl;
-
- print('url : $url');
- print(url.length);
- var userName = Provider.of<RefNameProvider>(context)
- .getRefName(widget.userInfo.userId, widget.userInfo.nickName);
- var local = WebData().getCity(widget.userInfo.city);
-
- var profession = WebData().getProffesionName(widget.userInfo.occupation);
-
- var birth = widget.userInfo.birthday;
- print('birth : $birth');
-
- var birthDay = DateTime.parse(birth);
- print(birthDay);
- var today = DateTime.now();
-
- var testAge = today.difference(birthDay);
- print(testAge.inDays);
-
- var age = testAge.inDays ~/ 365;
-
- var connectTip;
-
- if (isChating) {
- connectTip = I18n.of(context).chatting;
- } else {
- if (isReply) {
- connectTip = I18n.of(context).voice_msg.replaceFirst('/s1', userName);
- } else {
- connectTip = I18n.of(context).waitting_answer;
- }
- }
-
- return Container(
- child: Column(
- children: <Widget>[
- ClipRRect(
- borderRadius: BorderRadius.circular(0),
- child: url.length == 0
- ? SizedBox(
- height: 100,
- width: 100,
- child: Image.asset(R.assetsImagesDefaultNorAvatar))
- : CachedNetworkImage(
- width: 100,
- height: 100,
- imageUrl: url,
- placeholder: (context, url) => Padding(
- padding: EdgeInsets.all(5),
- child: CircularProgressIndicator(
- valueColor:
- AlwaysStoppedAnimation(Constants.BlueTextColor)),
- ),
- fit: BoxFit.cover,
- ),
- ),
- SizedBox(height: 5),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- Container(
- constraints: BoxConstraints(maxWidth: Screen.width - 50),
- child: Text(
- userName,
- style: TextStyle(fontSize: 20, color: Colors.white70),
- textScaleFactor: 1.0,
- overflow: TextOverflow.ellipsis,
- textAlign: TextAlign.center,
- )),
- fixedText(' $age', fontSize: 20, color: Colors.white70)
- ],
- ),
- SizedBox(height: 5),
- Text(
- '$local',
- style: TextStyle(fontSize: 16, color: Colors.white70),
- textScaleFactor: 1.0,
- textAlign: TextAlign.center,
- ),
- SizedBox(height: 5),
- Text(
- '$profession',
- style: TextStyle(fontSize: 16, color: Colors.white70),
- textScaleFactor: 1.0,
- textAlign: TextAlign.center,
- ),
- SizedBox(height: 20),
- Container(
- width: Screen.width - 50,
- child: Text(
- connectTip,
- //maxLines: 2,
- style: TextStyle(fontSize: 20, color: Colors.white70),
- textScaleFactor: 1.0,
- textAlign: TextAlign.center,
- )),
- ],
- ),
- );
- }
-
- _replayToolBar() {
- return Container(
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- children: <Widget>[
- //接听按钮
- RawMaterialButton(
- onPressed: () {
- MsgHandler.stopAudioRing();
- int myId = UserData().basicInfo.userId;
- MsgHandler.sendReplyAudioChatReq(friendId, true);
- _createRendererView(myId);
- },
- child: Icon(
- Icons.call,
- color: Colors.white,
- size: 35.0,
- ),
- shape: CircleBorder(),
- elevation: 2.0,
- fillColor: Colors.greenAccent,
- padding: const EdgeInsets.all(15.0),
- ),
- //挂断按钮
- RawMaterialButton(
- onPressed: () {
- _onExit(context);
- MsgHandler.stopAudioRing();
- MsgHandler.sendReplyAudioChatReq(friendId, false);
- },
- child: Icon(
- Icons.call_end,
- color: Colors.white,
- size: 35.0,
- ),
- shape: CircleBorder(),
- elevation: 2.0,
- fillColor: Colors.redAccent,
- padding: const EdgeInsets.all(15.0),
- )
- ]));
- }
-
- _bottomToolBar() {
- List<Widget> showWidgets = [
- Text(I18n.of(context).voicing,
- textScaleFactor: 1.0,
- style: TextStyle(fontSize: 11, color: Colors.white24),
- textAlign: TextAlign.center),
- SizedBox(height: 10),
- Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[
- Offstage(
- offstage: !isChating,
- child: UserData().giftSwitch > 0
- ? RawMaterialButton(
- onPressed: _showGiftSheet,
- child: Icon(
- IconData(0xe64e, fontFamily: Constants.IconFontFamily),
- color: Colors.blueAccent,
- size: 20.0,
- ),
- shape: CircleBorder(),
- elevation: 2.0,
- fillColor: Colors.white,
- padding: const EdgeInsets.all(12.0),
- )
- : SizedBox(width: 36, height: 36)),
-
- //挂断按钮
- RawMaterialButton(
- onPressed: () {
- MsgHandler.sendReplyAudioChatReq(friendId, false);
- _onExit(context);
- },
- child: Icon(
- Icons.call_end,
- color: Colors.white,
- size: 35.0,
- ),
- shape: CircleBorder(),
- elevation: 2.0,
- fillColor: Colors.redAccent,
- padding: const EdgeInsets.all(15.0),
- ),
-
- //是否外放
- Offstage(
- offstage: !isChating,
- child: RawMaterialButton(
- onPressed: _isSpeakPhone,
- child: new Icon(
- speakPhone ? Icons.volume_up : Icons.volume_down,
- color: Colors.blueAccent,
- size: 20.0,
- ),
- shape: new CircleBorder(),
- elevation: 2.0,
- fillColor: Colors.white,
- padding: const EdgeInsets.all(12.0),
- ))
- ])
- ];
-
- if (isChating) {
- showWidgets.insert(
- 0,
- Container(
- alignment: Alignment.center,
- height: 80,
- width: 200,
- child: CounterOverlay(),
- ));
- }
- return Container(
- child: Column(children: showWidgets),
- );
- }
-
- //创建渲染视图
- void _createRendererView(int uId) {
- //增加音频会话对象 为了音频布局需要(通过uid和容器信息)
- //加入频道 第一个参数是 token 第二个是频道id 第三个参数 频道信息 一般为空 第四个 用户id
- int myId = UserData().basicInfo.userId;
- setState(() {
- print('加入聊天房间');
- var channelName = UserData().getSessionId(friendId).toString();
-
- AgoraRtcEngine.joinChannel(null, channelName, null, myId);
- });
- }
-
- //设置事件监听
- void setAgoreEventListener() {
- //成功加入房间
- AgoraRtcEngine.onJoinChannelSuccess =
- (String channel, int uid, int elapsed) {
- print("加入成功id为:$uid elapsed:$elapsed");
- if (isReply) {
- //回应
- setState(() {
- isReply = false;
- isChating = true;
- });
- } else {
- // if(!widget.isTranslateButler){
- //
- // }
- MsgHandler.sendAudioChatReq(widget.userInfo.userId);
-
- callingTimer = Timer.periodic(Duration(milliseconds: 2200), (timer) {
- SoundUtils().play(
- 'http://testcyhd.chengyouhd.com/Upload/Audio/even_wheat_sound.mp3',
- isLocal: false);
- });
-
- //30没人接就自动挂断
- offTimer = Timer(Duration(seconds: 30), () {
- MsgHandler.sendReplyAudioChatReq(friendId, false);
- _onExit(context);
- });
- }
- };
-
- //监听是否有新用户加入
- AgoraRtcEngine.onUserJoined = (int uid, int elapsed) {
- print("新用户所加入的id为:$uid elapsed:$elapsed");
-
- setState(() {
- //更新UI布局
- SoundUtils().stop();
- callingTimer?.cancel();
- isChating = true;
- offTimer?.cancel();
- });
- };
-
- //监听用户是否离开这个房间
- AgoraRtcEngine.onUserOffline = (int uid, int reason) {
- print("用户离开的id为:$uid");
- _onExit(context);
- };
-
- AgoraRtcEngine.onError = (dynamic errCode) {
- print('通话异常');
- // _onExit(context);
- };
-
- //监听用户是否离开这个频道
- AgoraRtcEngine.onLeaveChannel = () {
- print("用户离开");
- };
- }
-
- void _showGiftSheet() {
- showModalBottomSheet(
- context: context,
- elevation: 2.0,
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(20), topRight: Radius.circular(20))),
- backgroundColor: Colors.transparent,
- builder: (BuildContext context) {
- return StatefulBuilder(
- builder: (BuildContext context, setBottomSheetState) {
- return Container(
- height: 400,
- width: Screen.width,
- decoration: BoxDecoration(
- color: Colors.white,
- ),
- child: giftList == null
- ? Center(
- child: Text(
- I18n.of(context).no_gift,
- textScaleFactor: 1.0,
- ))
- : Column(
- children: <Widget>[
- Container(
- // decoration: BoxDecoration(
- // color: Colors.orangeAccent,
- // borderRadius: borderRadius
- // ),
- padding: EdgeInsets.symmetric(
- vertical: 10, horizontal: 20),
- child: Row(
- children: <Widget>[
- Text(I18n.of(context).sent_gift,
- textScaleFactor: 1.0,
- style: TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.bold,
- color: Constants.BlackTextColor)),
- Expanded(
- child: SizedBox(),
- ),
- Image.asset(
- R.assetsImagesCoin,
- scale: 2,
- ),
- SizedBox(
- width: 5,
- ),
- fixedText(
- I18n.of(context)
- .available_balance
- .replaceFirst('/s1', ''),
- color: Constants.GreyTextColor),
- Consumer<MoneyChangeProvider>(
- builder: (context,
- MoneyChangeProvider counter,
- child) =>
- fixedText(counter.money.toString(),
- color: Color(0xFFDB305D)),
- ),
- fixedText(I18n.of(context).mask_coin,
- color: Color(0xFFDB305D)),
- ],
- ),
- ),
- Container(
- alignment: Alignment.topCenter,
- padding: EdgeInsets.all(10),
- height: 230,
- child: GiftPage(giftList, 0),
- ),
- Expanded(child: SizedBox()),
- Padding(
- padding: EdgeInsets.symmetric(
- vertical: 5, horizontal: 20),
- child: Row(
- children: <Widget>[
- Expanded(
- child: SizedBox(
- height: 36,
- child: RaisedButton(
- padding:
- EdgeInsets.symmetric(horizontal: 5),
- child: Text(
- I18n.of(context).recharge,
- textScaleFactor: 1.0,
- maxLines: 1,
- style: TextStyle(
- fontSize: 16,
- fontWeight: FontWeight.bold),
- ),
- elevation: 2.0,
- color: Colors.orangeAccent,
- textColor: Colors.white,
- onPressed: () {
- ChargeMoney.showChargeSheet(context,
- () {
- setState(() {});
- });
- },
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.all(
- Radius.circular(20)),
- ),
- ),
- )),
- SizedBox(width: 20),
- Expanded(
- flex: 2,
- child: Container(
- height: 36,
- decoration: BoxDecoration(
- boxShadow: [
- BoxShadow(
- blurRadius: 2.0,
- color: Colors.white24)
- ],
- borderRadius: BorderRadius.all(
- Radius.circular(20)),
- border: Border.all(
- color: Colors.red)),
- child: Row(
- children: <Widget>[
- Expanded(
- child: DropdownButton(
- isExpanded: true,
- underline: Container(),
- value: curGiftValue,
- style: TextStyle(fontSize: 16),
- iconEnabledColor:
- Colors.redAccent,
- onChanged: (newValue) {
- setBottomSheetState(() {
- curGiftValue = newValue;
- });
- },
- items: <int>[1, 6, 8, 66]
- .map<DropdownMenuItem>((v) => DropdownMenuItem(
- value: v,
- child: Container(
- padding:
- EdgeInsets.only(
- left: 20),
- child: fixedText(
- v.toString(),
- color: v == curGiftValue
- ? Colors
- .redAccent
- : Colors
- .black))))
- .toList(),
- )),
- Expanded(
- child: InkWell(
- child: Container(
- decoration: BoxDecoration(
- color: Color(0xFFFD6E8F),
- borderRadius:
- BorderRadius.only(
- topRight: Radius
- .circular(20),
- bottomRight:
- Radius.circular(
- 20)),
- ),
- height: 36,
- alignment: Alignment.center,
- child: Text(
- I18n.of(context).give,
- textScaleFactor: 1.0,
- style: TextStyle(
- color: Colors.white,
- fontSize: 16,
- fontWeight:
- FontWeight.bold),
- ),
- ),
- onTap: () {
- _sendGift(context);
- },
- ))
- ],
- )))
- ],
- ),
- )
- ],
- ));
- },
- );
- });
- }
-
- _sendGift(BuildContext context) async {
- int curSelectIndex =
- Provider.of<GiftSelectProvider>(context).curSelectIndex;
- var curGift = giftList[curSelectIndex];
-
- int price = curGift.price;
- int giftId = curGift.id;
- int total = curGiftValue * price;
- if (total > Provider.of<MoneyChangeProvider>(context).money) {
- showToast(I18n.of(context).not_enough);
- return;
- }
-
- int buyCount = 0;
- if (curGiftValue > curGift.amount) {
- buyCount = curGiftValue - curGift.amount;
- }
- Map data = {
- "userId": UserData().basicInfo.userId,
- "rUserId": friendId,
- "id": giftId,
- "price": price,
- "amount": curGiftValue,
- "totalPrice": total,
- "payNum": buyCount
- };
-
- data['sign'] = TokenMgr().getSign(data);
-
- Response res = await HttpUtil().post('reward/gift', data: data);
- if (res == null) {
- return;
- }
- Map resData = res.data;
-
- //showToast(resData['msg']);
-
- if (resData['code'] == 0) {
- //赠送成功
- print('赠送金额:${resData['data']}');
-
- int receiveAmount = resData['data'];
- Navigator.pop(context);
-
- Provider.of<MoneyChangeProvider>(context, listen: false).subMoney(total);
- AnimEffect.showEffect(context, giftId);
- AnimEffect.showDashangEffect(context, true, curGiftValue, curGift.name);
- MsgHandler.sendGiftTo(friendId, giftId, curGiftValue, receiveAmount);
-
- setState(() {});
- }
- }
-
- //是否开启扬声器
- void _isSpeakPhone() {
- setState(() {
- speakPhone = !speakPhone;
- });
- AgoraRtcEngine.setEnableSpeakerphone(speakPhone);
- }
-
- //退出频道 退出本页面
- void _onExit(BuildContext context) {
- if (!isQuit) {
- print('连麦关闭AAAA');
- if (Navigator.canPop(context)) {
- isQuit = true;
- print('连麦关闭BBBB');
- if(widget.translateButlerCloseCallBack!=null){
- print('连麦关闭CCCCCCCC');
-
- widget.translateButlerCloseCallBack(2);
- }else{
- Navigator.of(context).pop();
- }
-
- SoundUtils().stop();
- callingTimer?.cancel();
- }
- }
- }
- }
|