购买道具

This commit is contained in:
18631081161 2024-09-02 14:11:51 +08:00
parent 9954555d61
commit cffdc32553
28 changed files with 840 additions and 210 deletions

View File

@ -80,7 +80,7 @@ dependencies {
api 'com.tencent.mm.opensdk:wechat-sdk-android:6.8.30'
api 'org.greenrobot:eventbus:3.1.1'
api 'org.greenrobot:eventbus:3.3.1'
}
flutter {

View File

@ -1,8 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name="${applicationName}"

View File

@ -0,0 +1,20 @@
package com.huanmeng.talk;
/**
* Created by apple on 2016/11/7.
* eventBus变量
*/
public class EventBusParams {
/**
*
*/
public static final String GAME = "game";
public static final String MAIN = "main";
public static final String PUSH = "push";
}

View File

@ -61,12 +61,21 @@ public class MainActivity extends FlutterActivity {
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
if (event.message.equals("wxPaySuccess")) {
Map<String, String> map = new HashMap<>();
map.put("wxPaySuccess", "wxPaySuccess");
nativeChannel.invokeMethod("wxPaySuccess", map);
switch (event.message) {
case "wxPaySuccess":
Map<String, String> map = new HashMap<>();
map.put("wxPaySuccess", "wxPaySuccess");
nativeChannel.invokeMethod("wxPaySuccess", map);
break;
case "payError":
Map<String, String> mapError = new HashMap<>();
mapError.put("payError", "payError");
nativeChannel.invokeMethod("payError", mapError);
break;
}
}
@ -139,8 +148,8 @@ public class MainActivity extends FlutterActivity {
Log.d("TAG", "handleMessage: payResult==" + payResult);
Map<String, String> map = new HashMap<>();
map.put("AlipaySuccess", "AlipaySuccess");
nativeChannel.invokeMethod("AlipaySuccess", map);
map.put("payError", "payError");
nativeChannel.invokeMethod("payError", map);
}
break;

View File

@ -17,6 +17,7 @@ import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import org.greenrobot.eventbus.EventBus;
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private final String APP_ID = "wxa4009a51b6438a06";
@ -61,16 +62,19 @@ public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
case BaseResp.ErrCode.ERR_USER_CANCEL:
//发送取消
Log.d("TAG", "取消支付");
EventBus.getDefault().post(new MessageEvent("payError"));
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
//发送被拒绝
Log.d("TAG", "拒绝支付");
EventBus.getDefault().post(new MessageEvent("payError"));
break;
case BaseResp.ErrCode.ERR_UNSUPPORT:
//不支持错误
Log.d("TAG", "不支持支付");
EventBus.getDefault().post(new MessageEvent("payError"));
break;
default:
//发送返回
@ -79,12 +83,5 @@ public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
}
finish();
// Log.d("TAG", "onPayFinish, errCode = " + resp.errCode);
// if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
// Log.d("TAG", "onPayFinish,errCode=" + resp.errCode);
//
// finish();
// }
}
}

View File

@ -17,9 +17,10 @@ class CharacterInfoBean {
String? biography;
String? prologue;
List<LabelBean>? label;
bool? memoryCardState;
CharacterInfoBean(this.icon, this.intimacy, this.characterId, this.characterName, this.gender, this.lookCount, this.bgUrl, this.biography,
this.prologue, this.label);
this.prologue, this.label, this.memoryCardState);
factory CharacterInfoBean.fromJson(Map<String, dynamic> json) => _$CharacterInfoBeanFromJson(json);

View File

@ -20,6 +20,7 @@ CharacterInfoBean _$CharacterInfoBeanFromJson(Map<String, dynamic> json) =>
(json['label'] as List<dynamic>?)
?.map((e) => LabelBean.fromJson(e as Map<String, dynamic>))
.toList(),
json['memoryCardState'] as bool?,
);
Map<String, dynamic> _$CharacterInfoBeanToJson(CharacterInfoBean instance) =>
@ -34,4 +35,5 @@ Map<String, dynamic> _$CharacterInfoBeanToJson(CharacterInfoBean instance) =>
'biography': instance.biography,
'prologue': instance.prologue,
'label': instance.label?.map((e) => e.toJson()).toList(),
'memoryCardState': instance.memoryCardState,
};

View File

@ -6,14 +6,16 @@ part 'mall_item_bean.g.dart';
@JsonSerializable(explicitToJson: true)
class MallItemBean {
int? propId;
String? propName;
String? productId;
String? productDesc;
String? productName;
int? propCount;
int? propType;
int? price;
String? price;
int? priceType;
String? imgUrl;
MallItemBean(this.propId, this.propName, this.propCount, this.propType, this.price, this.priceType, this.imgUrl);
MallItemBean(this.propId, this.productId, this.productDesc, this.productName, this.propCount, this.propType, this.price, this.priceType, this.imgUrl);
factory MallItemBean.fromJson(Map<String, dynamic> json) => _$MallItemBeanFromJson(json);

View File

@ -8,10 +8,12 @@ part of 'mall_item_bean.dart';
MallItemBean _$MallItemBeanFromJson(Map<String, dynamic> json) => MallItemBean(
(json['propId'] as num?)?.toInt(),
json['propName'] as String?,
json['productId'] as String?,
json['productDesc'] as String?,
json['productName'] as String?,
(json['propCount'] as num?)?.toInt(),
(json['propType'] as num?)?.toInt(),
(json['price'] as num?)?.toInt(),
json['price'] as String?,
(json['priceType'] as num?)?.toInt(),
json['imgUrl'] as String?,
);
@ -19,7 +21,9 @@ MallItemBean _$MallItemBeanFromJson(Map<String, dynamic> json) => MallItemBean(
Map<String, dynamic> _$MallItemBeanToJson(MallItemBean instance) =>
<String, dynamic>{
'propId': instance.propId,
'propName': instance.propName,
'productId': instance.productId,
'productDesc': instance.productDesc,
'productName': instance.productName,
'propCount': instance.propCount,
'propType': instance.propType,
'price': instance.price,

View File

@ -0,0 +1,17 @@
import 'package:json_annotation/json_annotation.dart';
part 'memory_card_bean.g.dart';
///
@JsonSerializable(explicitToJson: true)
class MemoryCardBean {
int? propId;
String? propName;
String? imgUrl;
MemoryCardBean(this.propId, this.propName, this.imgUrl);
factory MemoryCardBean.fromJson(Map<String, dynamic> json) => _$MemoryCardBeanFromJson(json);
Map<String, dynamic> toJson() => _$MemoryCardBeanToJson(this);
}

View File

@ -0,0 +1,21 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'memory_card_bean.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
MemoryCardBean _$MemoryCardBeanFromJson(Map<String, dynamic> json) =>
MemoryCardBean(
(json['propId'] as num?)?.toInt(),
json['propName'] as String?,
json['imgUrl'] as String?,
);
Map<String, dynamic> _$MemoryCardBeanToJson(MemoryCardBean instance) =>
<String, dynamic>{
'propId': instance.propId,
'propName': instance.propName,
'imgUrl': instance.imgUrl,
};

View File

@ -0,0 +1,42 @@
import 'dart:async';
import 'package:event_bus/event_bus.dart';
class EventBusUtil {
static EventBus? _eventBus;
//
static EventBus getInstance() {
_eventBus ??= EventBus();
return _eventBus!;
}
//
static StreamSubscription<T> listen<T extends Event>(Function(T event) onData) {
_eventBus ??= EventBus();
//广
return _eventBus!.on<T>().listen(onData);
}
//
static void fire<T extends Event>(T e) {
_eventBus ??= EventBus();
_eventBus!.fire(e);
}
}
abstract class Event {}
class OrderStatusEvent extends Event {}
class PushStatusEvent extends Event {}
//
class RefreshUserdata extends Event {
RefreshUserdata();
}
//
class PaySuccess extends Event {
PaySuccess();
}

View File

@ -1,17 +1,22 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import '../network/NetworkConfig.dart';
import '../beans/memory_card_bean.dart';
class MemoryCardDialog extends StatefulWidget {
Function onTap;
MemoryCardDialog({required this.onTap});
List<MemoryCardBean> memoryCardList;
MemoryCardDialog({required this.onTap, required this.memoryCardList});
@override
State<MemoryCardDialog> createState() => _MemoryCardDialogState();
}
class _MemoryCardDialogState extends State<MemoryCardDialog> {
int currentIndex = 0;
@override
void initState() {
// TODO: implement initState
@ -36,31 +41,29 @@ class _MemoryCardDialogState extends State<MemoryCardDialog> {
decoration: BoxDecoration(color: Color(0xFF272734), borderRadius: BorderRadius.all(Radius.circular(7))),
),
Container(
margin: EdgeInsets.only(top: 38, left: 22, bottom: 19),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(color: Color(0xFF2A2A2A), borderRadius: BorderRadius.all(Radius.circular(7))),
child: Image(
width: 155,
height: 100,
image: AssetImage('assets/images/ic_memory_card.png'),
),
),
Container(
margin: EdgeInsets.only(left: 30),
child: Text(
"x ${NetworkConfig.userInfoBean?.memoryCardCount}",
style: TextStyle(color: Color(0xFFFF9000)),
),
)
],
),
height: 300,
margin: EdgeInsets.only(top: 38, left: 19, bottom: 10, right: 19),
child: GridView.count(
shrinkWrap: true,
//Widget之间间距
crossAxisSpacing: 12.0,
//Widget之间间距
mainAxisSpacing: 14.0,
//GridView内边距
padding: EdgeInsets.zero,
//Widget数量
crossAxisCount: 2,
//Widget宽高比例
childAspectRatio: 1.54,
//Widget列表
children: _item(),
// cellForRow
scrollDirection: Axis.vertical),
),
GestureDetector(
onTap: () {
widget.onTap();
Navigator.of(context).pop();
widget.onTap(widget.memoryCardList[currentIndex].propId);
},
child: Container(
width: double.infinity,
@ -82,4 +85,32 @@ class _MemoryCardDialogState extends State<MemoryCardDialog> {
),
);
}
_item() {
return widget.memoryCardList.map((res) {
int index = widget.memoryCardList.indexOf(res);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () {
currentIndex = index;
setState(() {});
},
child: Container(
decoration: BoxDecoration(
color: Color(0xFF2A2A2A),
border: Border.all(color: currentIndex == index ? Color(0xFFFF9000) : Color(0xFF2A2A2A), width: 1),
borderRadius: BorderRadius.all(Radius.circular(7))),
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: res.imgUrl!,
errorWidget: (context, url, error) => const Icon(Icons.error),
),
),
),
],
);
}).toList();
}
}

View File

@ -0,0 +1,173 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:talk/network/NetworkConfig.dart';
class PropPayDialog extends StatefulWidget {
Function onTap;
String priceImgUrl;
String productName;
String productDesc;
String price;
PropPayDialog(
{super.key, required this.onTap, required this.priceImgUrl, required this.productName, required this.productDesc, required this.price});
@override
State<PropPayDialog> createState() => _PropPayDialogState();
}
class _PropPayDialogState extends State<PropPayDialog> {
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Material(
type: MaterialType.transparency, //
color: Color(0x1A000000),
child: Container(
decoration: const BoxDecoration(
color: Color(0xFF19191A),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(7),
topRight: Radius.circular(7),
)),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 25,
height: 3,
margin: EdgeInsets.only(top: 14),
decoration: BoxDecoration(color: Color(0xFF272734)),
),
Container(
alignment: Alignment.centerLeft,
margin: EdgeInsets.only(top: 16, left: 16),
child: Text(
'购买道具',
style: TextStyle(fontSize: 16, color: Colors.white),
),
),
Container(
margin: EdgeInsets.only(top: 18, left: 16),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(7)),
child: Container(
color: Color(0xFF2A2A2A),
child: CachedNetworkImage(
width: 100,
height: 65,
fit: BoxFit.cover,
imageUrl: widget.priceImgUrl,
errorWidget: (context, url, error) => const Icon(Icons.error),
),
),
),
Container(
width: 180,
margin: EdgeInsets.only(left: 22),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.productName,
style: TextStyle(fontSize: 16, color: Colors.white),
),
Container(
margin: EdgeInsets.only(top: 11),
child: Text(
widget.productDesc,
style: TextStyle(fontSize: 12, color: Color(0xFF9E9E9E)),
),
)
],
),
),
],
),
),
Container(
height: 1,
margin: EdgeInsets.only(top: 23, left: 16, right: 16),
color: Color(0xFF484848),
),
Container(
margin: EdgeInsets.only(top: 20, left: 16, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"账户余额${NetworkConfig.userInfoBean?.currency}语珠",
style: TextStyle(fontSize: 14, color: Color(0xFF9E9E9E)),
),
Text(
"合计 ${widget.price}语珠",
style: TextStyle(fontSize: 14, color: Colors.white),
),
],
),
),
Container(
height: 1,
margin: EdgeInsets.only(top: 23, left: 16, right: 16),
color: Color(0xFF484848),
),
Container(
margin: EdgeInsets.only(left: 16, right: 16, top: 25, bottom: 36),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
Navigator.of(context).pop();
},
child: Container(
width: 159,
height: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFF555555),
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Text(
"取消",
style: TextStyle(fontSize: 16, color: Colors.white),
),
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
widget.onTap();
Navigator.of(context).pop();
},
child: Container(
width: 159,
height: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFFFF9000),
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Text(
"购买",
style: TextStyle(fontSize: 16, color: Colors.black),
),
),
),
],
),
),
],
)),
);
}
}

View File

@ -21,6 +21,7 @@ import 'package:talk/tools/shop/problem_page.dart';
import 'package:talk/tools/shop/shop_page.dart';
import 'package:talk/tools/start_page.dart';
import 'common/EventBusUtil.dart';
import 'common/Global.dart';
Future<void> main() async {
@ -56,13 +57,17 @@ class _ChatAppState extends State<ChatApp> {
break;
case "AlipaySuccess": //
print("AlipaySuccess6666666666666");
EasyLoading.showToast("支付成功");
// EasyLoading.showToast("支付成功");
EventBusUtil.fire(PaySuccess());
break;
case "wxPaySuccess": //
print("wxPaySuccess6666666666666");
EasyLoading.showToast("微信支付成功");
case "wxPaySuccess": //
// EasyLoading.showToast("微信支付成功");
EventBusUtil.fire(PaySuccess());
break;
case "payError": //
EasyLoading.showToast("支付失败");
break;
}
}

View File

@ -1,3 +1,4 @@
import '../beans/memory_card_bean.dart';
import '../beans/user_info_bean.dart';
class NetworkConfig {
@ -30,6 +31,9 @@ class NetworkConfig {
static UserInfoBean? userInfoBean;
static bool isTeenage = false; //
static String teenagePassword = ""; //
static String orderId = ""; //
static String currencyNum = ""; //
static List<MemoryCardBean> memoryCardList = []; //
static const String accountLogin = "api/Account/AccountLogIn"; //
static const String sendPhoneNumber = "api/Account/SendPhoneNumber"; //
@ -65,4 +69,12 @@ class NetworkConfig {
static const String logout = "api/Account/Logout"; //
static const String createOrder = "api/Payment/CreateOrder"; //
static const String getOrderRewardsInfo = "api/Payment/GetOrderRewardsInfo"; //
static const String buyProduct = "api/Payment/BuyProduct"; //
static const String getMemoryCardInfo = "api/Chat/GetMemoryCardInfo"; //
static const String useMemoryCard = "api/Chat/UseMemoryCard"; //使
}

View File

@ -5,6 +5,7 @@ import 'package:talk/network/RequestCenter.dart';
import '../../beans/character_info_bean.dart';
import '../../beans/chat_info_bean.dart';
import '../../beans/memory_card_bean.dart';
import '../../beans/send_message_bean.dart';
import '../../network/BaseEntity.dart';
@ -20,7 +21,6 @@ class ChatModel {
///
Future<void> getCharacterInfo(characterId) async {
RequestCenter.instance.requestGet(NetworkConfig.getCharacterInfo, {"characterId": characterId}, (BaseEntity dataEntity) {
if (dataEntity.code == 0) {
CharacterInfoBean characterInfoBean = CharacterInfoBean.fromJson(dataEntity.data);
@ -30,7 +30,7 @@ class ChatModel {
});
} else {
streamController.sink.add({
'code': "-1", //
'code': "error", //
'data': dataEntity.message
});
}
@ -47,14 +47,13 @@ class ChatModel {
if (dataEntity.code == 0) {
List<ChatInfoBean> data = (dataEntity.data as List<dynamic>).map((e) => ChatInfoBean.fromJson(e as Map<String, dynamic>)).toList();
streamController.sink.add({
'code': "getChatInfo", //
'data': data
});
} else {
streamController.sink.add({
'code': "-1", //
'code': "error", //
'data': dataEntity.message
});
}
@ -104,7 +103,7 @@ class ChatModel {
});
} else {
streamController.sink.add({
'code': "-1", //
'code': "error", //
'data': dataEntity.message
});
}
@ -127,7 +126,7 @@ class ChatModel {
});
} else {
streamController.sink.add({
'code': "-1", //
'code': "error", //
'data': dataEntity.message
});
}
@ -135,4 +134,40 @@ class ChatModel {
print("errorEntity==${errorEntity.message}");
});
}
///使
Future<void> useMemoryCard(propId, characterId) async {
RequestCenter.instance.request(NetworkConfig.useMemoryCard, {
"propId": propId,
"characterId": characterId,
}, (BaseEntity dataEntity) {
if (dataEntity.code == 0) {
getMemoryCardInfo();
streamController.sink.add({
'code': "useMemoryCard", //
'data': dataEntity.message
});
} else {
streamController.sink.add({
'code': "error", //
'data': dataEntity.message
});
}
}, (ErrorEntity errorEntity) {
print("errorEntity==${errorEntity.message}");
});
}
///
Future<void> getMemoryCardInfo() async {
RequestCenter.instance.requestGet(NetworkConfig.getMemoryCardInfo, {}, (BaseEntity dataEntity) {
List<MemoryCardBean> data = (dataEntity.data as List<dynamic>).map((e) => MemoryCardBean.fromJson(e as Map<String, dynamic>)).toList();
if (dataEntity.code == 0) {
NetworkConfig.memoryCardList = data;
}
}, (ErrorEntity errorEntity) {
print("errorEntity==${errorEntity.message}");
});
}
}

View File

@ -7,6 +7,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:fluttertoast/fluttertoast.dart';
import '../../beans/character_info_bean.dart';
import '../../beans/chat_info_bean.dart';
@ -15,7 +16,9 @@ import '../../common/func.dart';
import '../../custom/DynamicText.dart';
import '../../custom/custom_popup.dart';
import '../../dialog/delete_dialog.dart';
import '../../dialog/memory_card_dialog.dart';
import '../../dialog/restart_chat_dialog.dart';
import '../../network/NetworkConfig.dart';
import 'chat_info_page.dart';
import 'chat_model.dart';
@ -37,7 +40,7 @@ class _ChatPageState extends State<ChatPage> {
final FocusNode _focusNode = FocusNode();
///
CharacterInfoBean? characterInfoBean;
late CharacterInfoBean characterInfoBean;
///
late SendMessageBean sendMessageBean;
@ -65,6 +68,8 @@ class _ChatPageState extends State<ChatPage> {
int delIndex = 0;
bool memoryCardState = false;
///
void _scrollToBottom() {
Future.delayed(Duration(milliseconds: 300), () {
@ -87,6 +92,7 @@ class _ChatPageState extends State<ChatPage> {
switch (code) {
case "getCharacterInfo":
characterInfoBean = newData['data'];
memoryCardState = characterInfoBean.memoryCardState!;
_viewmodel.getChatInfo(widget.characterId);
break;
case "getChatInfo":
@ -136,6 +142,18 @@ class _ChatPageState extends State<ChatPage> {
EasyLoading.dismiss();
break;
case "useMemoryCard": //使
memoryCardState = true;
Fluttertoast.showToast(
msg: newData['data'],
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
textColor: Colors.white,
backgroundColor: Colors.black.withOpacity(0.5),
);
break;
default:
EasyLoading.dismiss();
EasyLoading.showToast(newData['data']);
@ -211,12 +229,12 @@ class _ChatPageState extends State<ChatPage> {
backgroundColor: Color(0xFF121213),
body: Stack(
children: [
characterInfoBean != null && characterInfoBean?.bgUrl != null
characterInfoBean.bgUrl != null
? CachedNetworkImage(
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
imageUrl: "${characterInfoBean?.bgUrl}",
imageUrl: "${characterInfoBean.bgUrl}",
errorWidget: (context, url, error) => const Icon(Icons.error),
)
: Container(),
@ -282,7 +300,7 @@ class _ChatPageState extends State<ChatPage> {
context,
MaterialPageRoute(
builder: (context) => ChatInfoPage(
data: characterInfoBean!,
data: characterInfoBean,
)),
);
},
@ -292,7 +310,7 @@ class _ChatPageState extends State<ChatPage> {
child: CachedNetworkImage(
width: 23,
height: 23,
imageUrl: '${characterInfoBean?.icon}',
imageUrl: '${characterInfoBean.icon}',
errorWidget: (context, url, error) => const Icon(Icons.error),
),
),
@ -309,7 +327,7 @@ class _ChatPageState extends State<ChatPage> {
SizedBox(
width: h35,
child: Text(
"${characterInfoBean?.characterName}",
"${characterInfoBean.characterName}",
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 11, color: Colors.white),
),
@ -317,7 +335,7 @@ class _ChatPageState extends State<ChatPage> {
SizedBox(
width: h35,
child: Text(
'${characterInfoBean?.lookCount} 聊过',
'${characterInfoBean.lookCount} 聊过',
style: TextStyle(fontSize: 9, color: Color(0xFFBDBDBD)),
),
),
@ -325,6 +343,13 @@ class _ChatPageState extends State<ChatPage> {
),
),
memoryCardState
? Container(
margin: EdgeInsets.only(right: 5),
child: Image(width: 24, height: 24, image: AssetImage('assets/images/ic_memory.png')),
)
: Container(),
///
// Container(
// margin: EdgeInsets.only(left: 6, right: 6),
@ -588,6 +613,42 @@ class _ChatPageState extends State<ChatPage> {
),
),
Container(
margin: EdgeInsets.only(left: l50),
child: GestureDetector(
onTap: () {
setState(() {
isMore = false;
});
if (NetworkConfig.memoryCardList.isNotEmpty) {
FunctionUtil.bottomSheetDialog(
context,
MemoryCardDialog(
onTap: (propId) {
_viewmodel.useMemoryCard(propId, widget.characterId);
},
memoryCardList: NetworkConfig.memoryCardList,
));
} else {
Navigator.pushNamed(context, "/ShopPage");
}
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image(width: 26, height: 26, image: AssetImage('assets/images/ic_memory.png')),
Container(
margin: EdgeInsets.only(top: 9),
child: Text(
'记忆提升',
style: TextStyle(fontSize: 10, color: Color(0xFFA2A2A2)),
),
),
],
),
),
),
Container(
margin: EdgeInsets.only(left: l50),
child: GestureDetector(
@ -609,39 +670,6 @@ class _ChatPageState extends State<ChatPage> {
),
),
),
// Container(
// margin: EdgeInsets.only(left: l50),
// child: GestureDetector(
// onTap: () {
// setState(() {
// isMore = false;
// });
// if (NetworkConfig.userInfoBean!.memoryCardCount! > 0) {
// FunctionUtil.bottomSheetDialog(context, MemoryCardDialog(
// onTap: () {
// EasyLoading.showToast("status");
// },
// ));
// } else {
// Navigator.pushNamed(context, "/ShopPage");
// }
// },
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// Image(width: 26, height: 26, image: AssetImage('assets/images/ic_memory.png')),
// Container(
// margin: EdgeInsets.only(top: 9),
// child: Text(
// '记忆提升',
// style: TextStyle(fontSize: 10, color: Color(0xFFA2A2A2)),
// ),
// ),
// ],
// ),
// ),
// ),
],
),
)

View File

@ -94,8 +94,7 @@ class _RecommendPageState extends State<RecommendPage> with AutomaticKeepAliveCl
final t21 = size.width / 17.14285714285714;
final h330 = size.width / 1.090909090909091;
final t34 = size.width / 10.58823529411765;
final b60 = size.width / 6;
final h153 = size.width / 2.352941176470588;
final h165 = size.width / 2.181818181818182;
return Stack(
children: [
@ -178,8 +177,8 @@ class _RecommendPageState extends State<RecommendPage> with AutomaticKeepAliveCl
),
),
Container(
height: h153 * (popularList.length),
margin: EdgeInsets.only(left: l16, right: l16, bottom: b60),
height: h165 * (popularList.length),
margin: EdgeInsets.only(left: l16, right: l16),
child: ListView.builder(
itemCount: popularList.length,
physics: NeverScrollableScrollPhysics(),

View File

@ -7,6 +7,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:fluttertoast/fluttertoast.dart';
import '../../beans/character_info_bean.dart';
import '../../beans/chat_info_bean.dart';
@ -16,6 +17,7 @@ import '../../common/func.dart';
import '../../custom/DynamicText.dart';
import '../../custom/custom_popup.dart';
import '../../dialog/delete_dialog.dart';
import '../../dialog/memory_card_dialog.dart';
import '../../dialog/restart_chat_dialog.dart';
import '../../network/NetworkConfig.dart';
import '../chat/chat_info_page.dart';
@ -67,6 +69,8 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
int delIndex = 0;
bool memoryCardState = false;
@override
void initState() {
// TODO: implement initState
@ -78,6 +82,7 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
switch (code) {
case "getCharacterInfo":
characterInfoBean = newData['data'];
memoryCardState = characterInfoBean.memoryCardState!;
_viewmodel.getChatInfo(widget.characterId);
break;
case "getChatInfo":
@ -128,8 +133,19 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
EasyLoading.dismiss();
break;
case "useMemoryCard": //使
memoryCardState = true;
Fluttertoast.showToast(
msg: newData['data'],
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
textColor: Colors.white,
backgroundColor: Colors.black.withOpacity(0.5),
);
break;
default:
EasyLoading.dismiss();
EasyLoading.showToast(newData['data']);
break;
}
@ -312,6 +328,13 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
),
),
memoryCardState
? Container(
margin: EdgeInsets.only(right: 5),
child: Image(width: 24, height: 24, image: AssetImage('assets/images/ic_memory.png')),
)
: Container(),
///
// Container(
// margin: EdgeInsets.only(left: 6, right: 6),
@ -524,7 +547,6 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
// "test": "test",
// };
// invokeNativeMethod("test", map);
},
child: Container(
margin: EdgeInsets.only(left: 14),
@ -592,7 +614,41 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
),
),
),
Container(
margin: EdgeInsets.only(left: l50),
child: GestureDetector(
onTap: () {
setState(() {
isMore = false;
});
if (NetworkConfig.memoryCardList.isNotEmpty) {
FunctionUtil.bottomSheetDialog(
context,
MemoryCardDialog(
onTap: (propId) {
_viewmodel.useMemoryCard(propId, widget.characterId);
},
memoryCardList: NetworkConfig.memoryCardList,
));
} else {
Navigator.pushNamed(context, "/ShopPage");
}
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Image(width: 26, height: 26, image: AssetImage('assets/images/ic_memory.png')),
Container(
margin: EdgeInsets.only(top: 9),
child: Text(
'记忆提升',
style: TextStyle(fontSize: 10, color: Color(0xFFA2A2A2)),
),
),
],
),
),
),
Container(
margin: EdgeInsets.only(left: l50),
child: GestureDetector(
@ -614,41 +670,6 @@ class _HomeChatPageState extends State<HomeChatPage> with AutomaticKeepAliveClie
),
),
),
// Container(
// margin: EdgeInsets.only(left: l50),
// child: GestureDetector(
// onTap: () {
// setState(() {
// isMore = false;
// });
// // EasyLoading.show(status: 'loading...');
// // _viewmodel.delChat(widget.characterId);
// if (NetworkConfig.userInfoBean!.memoryCardCount! > 0) {
// FunctionUtil.bottomSheetDialog(context, MemoryCardDialog(
// onTap: () {
// EasyLoading.showToast("status");
// },
// ));
// } else {
// Navigator.pushNamed(context, "/ShopPage");
// }
// },
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// Image(width: 26, height: 26, image: AssetImage('assets/images/ic_memory.png')),
// Container(
// margin: EdgeInsets.only(top: 9),
// child: Text(
// '记忆提升',
// style: TextStyle(fontSize: 10, color: Color(0xFFA2A2A2)),
// ),
// ),
// ],
// ),
// ),
// ),
],
),
)

View File

@ -3,8 +3,8 @@ import 'dart:async';
import 'package:talk/network/NetworkConfig.dart';
import 'package:talk/network/RequestCenter.dart';
import '../../beans/character_info_bean.dart';
import '../../beans/home_character_bean.dart';
import '../../beans/memory_card_bean.dart';
import '../../network/BaseEntity.dart';
class HomeModel {
@ -27,7 +27,7 @@ class HomeModel {
'code': "getCharacterIdList", //
'data': data
});
}else{
} else {
streamController.sink.add({
'code': "-1", //
'data': dataEntity.message
@ -38,4 +38,16 @@ class HomeModel {
});
}
///
Future<void> getMemoryCardInfo() async {
RequestCenter.instance.requestGet(NetworkConfig.getMemoryCardInfo, {}, (BaseEntity dataEntity) {
List<MemoryCardBean> data = (dataEntity.data as List<dynamic>).map((e) => MemoryCardBean.fromJson(e as Map<String, dynamic>)).toList();
if (dataEntity.code == 0) {
NetworkConfig.memoryCardList = data;
}
}, (ErrorEntity errorEntity) {
print("errorEntity==${errorEntity.message}");
});
}
}

View File

@ -46,7 +46,7 @@ class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateM
});
_viewmodel.getCharacterIdList();
// _viewmodel.getCharacterInfo(1);
_viewmodel.getMemoryCardInfo();
}
@override

View File

@ -216,7 +216,7 @@ class _MePageState extends State<MePage> {
},
child: Container(
height: t38,
decoration: BoxDecoration(color: Color(0xFF2A2A2A), borderRadius: BorderRadius.all(Radius.circular(13))),
decoration: BoxDecoration(color: Color(0xFF2A2A2A), borderRadius: BorderRadius.all(Radius.circular(7))),
child: Row(
children: [
Container(
@ -247,7 +247,7 @@ class _MePageState extends State<MePage> {
},
child: Container(
height: t38,
decoration: const BoxDecoration(color: Color(0xFF2A2A2A), borderRadius: BorderRadius.all(Radius.circular(13))),
decoration: const BoxDecoration(color: Color(0xFF2A2A2A), borderRadius: BorderRadius.all(Radius.circular(7))),
child: Row(
children: [
Container(

View File

@ -3,6 +3,8 @@ import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:talk/common/EventBusUtil.dart';
import 'package:talk/tools/shop/shop_model.dart';
import 'package:talk/tools/shop/transaction_page.dart';
@ -12,6 +14,7 @@ import '../../beans/transaction_records_bean.dart';
import '../../common/Global.dart';
import '../../common/func.dart';
import '../../dialog/payment_method_dialog.dart';
import '../me/agreement_page.dart';
///
class AccountPage extends StatefulWidget {
@ -28,17 +31,25 @@ class _AccountPageState extends State<AccountPage> {
late AccountBean accountBean;
List<TransactionRecordsBean> recordList = [];
StreamSubscription<PaySuccess>? _paySuccess;
@override
void initState() {
// TODO: implement initState
super.initState();
//
_paySuccess = EventBusUtil.listen((event) {
_viewmodel.getOrderRewardsInfo();
});
subscription = _viewmodel.streamController.stream.listen((newData) {
String code = newData['code'];
if (code.isNotEmpty) {
switch (code) {
case "getMyAccount":
accountBean = newData['data'];
// EasyLoading.dismiss();
break;
case "getTransactionRecords":
recordList = newData['data'];
@ -60,12 +71,26 @@ class _AccountPageState extends State<AccountPage> {
"orderInfoZfb": createOrderBean.payment,
};
invokeNativeMethod("Alipay", map);
break;
case "getOrderRewardsInfo": //
loadData();
EasyLoading.showToast(newData['data']);
break;
default:
EasyLoading.dismiss();
EasyLoading.showToast(newData['data']);
break;
}
setState(() {});
}
});
// EasyLoading.show(status: 'loading...');
loadData();
}
loadData() {
_viewmodel.getMyAccount();
_viewmodel.getTransactionRecords();
}
@ -79,6 +104,11 @@ class _AccountPageState extends State<AccountPage> {
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final w45 = size.width / 8;
final t39 = size.width / 9.230769230769231;
final h35 = size.width / 10.28571428571429;
return Scaffold(
backgroundColor: Color(0xFF121213),
appBar: AppBar(
@ -106,7 +136,7 @@ class _AccountPageState extends State<AccountPage> {
mainAxisSize: MainAxisSize.min,
children: [
Image(
width: 45,
width: w45,
image: AssetImage('assets/images/ic_pearl.png'),
),
Container(
@ -119,7 +149,7 @@ class _AccountPageState extends State<AccountPage> {
),
Container(
alignment: Alignment.centerLeft,
margin: EdgeInsets.only(top: 39),
margin: EdgeInsets.only(top: t39),
child: Text(
'账户充值',
style: TextStyle(fontSize: 13, color: Color(0xFFACACAC)),
@ -147,7 +177,7 @@ class _AccountPageState extends State<AccountPage> {
),
Container(
margin: EdgeInsets.only(top: 14),
decoration: BoxDecoration(color: Color(0xFF2A2A2A), borderRadius: BorderRadius.all(Radius.circular(17))),
decoration: BoxDecoration(color: Color(0xFF2A2A2A), borderRadius: BorderRadius.all(Radius.circular(7))),
child: Column(
children: [
GestureDetector(
@ -161,9 +191,9 @@ class _AccountPageState extends State<AccountPage> {
recordList: recordList,
)));
},
child: const SizedBox(
height: 35,
child: Stack(
child: SizedBox(
height: h35,
child: const Stack(
alignment: Alignment.center,
children: [
Positioned(
@ -192,11 +222,19 @@ class _AccountPageState extends State<AccountPage> {
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
Navigator.pushNamed(context, '/ProblemPage');
// Navigator.pushNamed(context, '/ProblemPage');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AgreementPage(
title: "常见问题",
url: "https://shhuanmeng.com/shangcheng.html",
)),
);
},
child: SizedBox(
height: 35,
child: Stack(
height: h35,
child: const Stack(
alignment: Alignment.center,
children: [
Positioned(
@ -225,6 +263,34 @@ class _AccountPageState extends State<AccountPage> {
],
),
),
Container(
margin: EdgeInsets.only(top: 22),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"充值代表已阅读并同意",
style: TextStyle(fontSize: 10, color: Color(0xFF686868)),
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AgreementPage(
title: "常见问题",
url: "https://shhuanmeng.com/shangcheng.html",
)),
);
},
child: Text(
"《充值协议》",
style: TextStyle(fontSize: 10, color: Color(0xFF969696)),
),
),
],
),
),
],
),
),
@ -234,50 +300,23 @@ class _AccountPageState extends State<AccountPage> {
_item() {
return accountBean.currencyRechargeList!.map((res) {
return Container(
height: 58,
decoration: BoxDecoration(color: Color(0xFF2A2A2A), borderRadius: BorderRadius.all(Radius.circular(17))),
child: Stack(
children: [
GestureDetector(
onTap: () {
FunctionUtil.bottomSheetDialog(context, PaymentMethodDialog(
onTap: (isWX) {
_viewmodel.createOrder(res.productId.toString(), isWX ? "wx" : "zfb");
},
));
},
child: CachedNetworkImage(
// width: 155,
// height: 100,
fit: BoxFit.cover,
imageUrl: res.imgUrl!,
errorWidget: (context, url, error) => const Icon(Icons.error),
),
return Stack(
children: [
GestureDetector(
onTap: () {
FunctionUtil.bottomSheetDialog(context, PaymentMethodDialog(
onTap: (isWX) {
_viewmodel.createOrder(res.productId.toString(), isWX ? "wx" : "zfb");
},
));
},
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: res.imgUrl!,
errorWidget: (context, url, error) => const Icon(Icons.error),
),
// Positioned(
// left: 21,
// top: 14,
// child: Text(
// '${res.currencyCount}',
// style: TextStyle(color: Color(0xFFFF9000), fontSize: 13),
// )),
// Positioned(
// left: 48,
// top: 16,
// child: Text(
// '语珠',
// style: TextStyle(color: Color(0xFF6F6F6F), fontSize: 10),
// )),
// Positioned(
// left: 21,
// top: 34,
// child: Text(
// '${res.price}',
// style: TextStyle(color: Colors.white, fontSize: 10),
// )),
],
),
),
],
);
}).toList();
}

View File

@ -6,7 +6,9 @@ import 'package:talk/network/RequestCenter.dart';
import '../../beans/account_bean.dart';
import '../../beans/create_order_bean.dart';
import '../../beans/mall_bean.dart';
import '../../beans/memory_card_bean.dart';
import '../../beans/transaction_records_bean.dart';
import '../../beans/user_info_bean.dart';
import '../../network/BaseEntity.dart';
class ShopModel {
@ -90,7 +92,7 @@ class ShopModel {
}, (BaseEntity dataEntity) {
if (dataEntity.code == 0) {
CreateOrderBean createOrderBean = CreateOrderBean.fromJson(dataEntity.data);
NetworkConfig.orderId = createOrderBean.orderId.toString();
print("dataEntity.data==${dataEntity.data}");
if (paymentMethod == "wx") {
@ -114,4 +116,77 @@ class ShopModel {
print("errorEntity==${errorEntity.message}");
});
}
///
Future<void> getOrderRewardsInfo() async {
RequestCenter.instance.requestGet(NetworkConfig.getOrderRewardsInfo, {
"orderId": NetworkConfig.orderId,
}, (BaseEntity dataEntity) {
if (dataEntity.code == 0) {
print("dataEntity.data==${dataEntity.data}");
getUserInfo();
streamController.sink.add({
'code': "getOrderRewardsInfo", //
'data': dataEntity.message,
});
} else {
streamController.sink.add({
'code': "error", //
'data': dataEntity.message,
});
}
}, (ErrorEntity errorEntity) {
print("errorEntity==${errorEntity.message}");
});
}
///
Future<void> buyProduct(productId, buyCount) async {
RequestCenter.instance.request(NetworkConfig.buyProduct, {
"productId": productId,
"buyCount": buyCount,
}, (BaseEntity dataEntity) {
if (dataEntity.code == 0) {
print("dataEntity.data==${dataEntity.data}");
getUserInfo();
getMemoryCardInfo();
streamController.sink.add({
'code': "buyProduct", //
'data': dataEntity.message,
});
} else {
streamController.sink.add({
'code': "error", //
'data': dataEntity.message,
});
}
}, (ErrorEntity errorEntity) {
print("errorEntity==${errorEntity.message}");
});
}
///
Future<void> getMemoryCardInfo() async {
RequestCenter.instance.requestGet(NetworkConfig.getMemoryCardInfo, {}, (BaseEntity dataEntity) {
List<MemoryCardBean> data = (dataEntity.data as List<dynamic>).map((e) => MemoryCardBean.fromJson(e as Map<String, dynamic>)).toList();
if (dataEntity.code == 0) {
NetworkConfig.memoryCardList = data;
}
}, (ErrorEntity errorEntity) {
print("errorEntity==${errorEntity.message}");
});
}
///
Future<void> getUserInfo() async {
RequestCenter.instance.requestGet(NetworkConfig.getUserInfo, {}, (BaseEntity dataEntity) {
if (dataEntity.code == 0) {
UserInfoBean userInfoBean = UserInfoBean.fromJson(dataEntity.data);
NetworkConfig.userInfoBean = userInfoBean;
}
}, (ErrorEntity errorEntity) {
print("errorEntity==${errorEntity.message}");
});
}
}

View File

@ -2,10 +2,13 @@ import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:talk/tools/shop/shop_model.dart';
import '../../beans/mall_bean.dart';
import '../../beans/mall_item_bean.dart';
import '../../common/func.dart';
import '../../dialog/prop_pay_dialog.dart';
///
class ShopPage extends StatefulWidget {
@ -36,6 +39,14 @@ class _ShopPageState extends State<ShopPage> {
case "getMallItem":
mallBean = newData['data'];
break;
case "buyProduct":
EasyLoading.showToast(newData['data']);
_viewmodel.getMallItem();
break;
default:
EasyLoading.dismiss();
EasyLoading.showToast(newData['data']);
break;
}
setState(() {});
}
@ -146,9 +157,9 @@ class _ShopPageState extends State<ShopPage> {
//Widget数量
crossAxisCount: 2,
//Widget宽高比例
childAspectRatio: 1.0,
childAspectRatio: currentIndex == 0 ? 1.0 : 1.2,
//Widget列表
children: _item(currentIndex == 0 ? mallBean.mall! : mallBean.purchased!),
children: currentIndex == 0 ? _item(mallBean.mall!) : _item2(mallBean.purchased!),
physics: NeverScrollableScrollPhysics(),
// cellForRow
scrollDirection: Axis.vertical),
@ -162,16 +173,88 @@ class _ShopPageState extends State<ShopPage> {
_item(List<MallItemBean> list) {
return list.map((res) {
// double类型
double priceDouble = double.parse(res.price.toString());
//
int price = priceDouble.toInt();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(15)),
child: CachedNetworkImage(
width: 155,
height: 100,
fit: BoxFit.cover,
imageUrl: res.imgUrl!,
errorWidget: (context, url, error) => const Icon(Icons.error),
GestureDetector(
onTap: () {
FunctionUtil.bottomSheetDialog(
context,
PropPayDialog(
onTap: () {
EasyLoading.show(status: "loading...");
_viewmodel.buyProduct(res.productId, 0);
},
price: price.toString(),
priceImgUrl: res.imgUrl.toString(),
productName: res.productName.toString(),
productDesc: res.productDesc.toString(),
));
},
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(7)),
child: Container(
color: Color(0xFF2A2A2A),
child: CachedNetworkImage(
width: 155,
height: 100,
fit: BoxFit.cover,
imageUrl: res.imgUrl!,
errorWidget: (context, url, error) => const Icon(Icons.error),
),
),
),
),
Container(
margin: EdgeInsets.only(top: 11),
child: Text(
"${res.productName}",
style: TextStyle(fontSize: 10, color: Colors.white),
),
),
Container(
margin: EdgeInsets.only(top: 11),
child: Text(
"$price 语珠",
style: TextStyle(fontSize: 9, color: Color(0xFFFF9000)),
),
),
],
);
}).toList();
}
_item2(List<MallItemBean> list) {
return list.map((res) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () {},
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(7)),
child: Container(
color: Color(0xFF2A2A2A),
child: CachedNetworkImage(
width: 155,
height: 100,
fit: BoxFit.cover,
imageUrl: res.imgUrl!,
errorWidget: (context, url, error) => const Icon(Icons.error),
),
),
),
),
Container(
margin: EdgeInsets.only(top: 11),
child: Text(
"${res.productName}",
style: TextStyle(fontSize: 10, color: Colors.white),
),
),
],

View File

@ -51,9 +51,11 @@ class _TransactionPageState extends State<TransactionPage> {
}
_item(index,TransactionRecordsBean data) {
final size = MediaQuery.of(context).size;
final h70 = size.width / 5.142857142857143;
return Container(
width: double.infinity,
height: 70,
height: h70,
child: Stack(
alignment: Alignment.center,
children: [
@ -83,7 +85,7 @@ class _TransactionPageState extends State<TransactionPage> {
Positioned(
right: 0,
child: Text(
'${data.transactionAmount}',
'${data.transactionAmount}',
style: TextStyle(fontSize: 11, color: Colors.white),
)),
],

View File

@ -51,6 +51,8 @@ dependencies:
webview_flutter: ^4.8.0
package_info_plus: ^8.0.0
flutter_verification_code: ^1.1.7
event_bus: ^2.0.0
fluttertoast: ^8.2.8
dev_dependencies:
flutter_test: