Commit 363514eb by tanghuan

增加提示信息,增加对用户角色数据的处理

1 parent 2e3fcdbe
...@@ -10,24 +10,23 @@ class LoginMainState extends Equatable { ...@@ -10,24 +10,23 @@ class LoginMainState extends Equatable {
final bool agreed; final bool agreed;
final bool showAgreed; final bool showAgreed;
final bool loading; final bool loading;
final bool showSnackBar;
final String snackBarMsg;
const LoginMainState({ const LoginMainState({
this.agreed = false, this.agreed = false,
this.showAgreed = false, this.showAgreed = false,
this.loading = false, this.loading = false,
this.showSnackBar = false,
this.snackBarMsg = '',
}); });
@override
List<Object?> get props => [
agreed,
showAgreed,
loading,
];
LoginMainState copyWith({ LoginMainState copyWith({
bool? agreed, bool? agreed,
bool? showAgreed, bool? showAgreed,
bool? loading, bool? loading,
bool? showSnackBar,
String? snackBarMsg,
}) { }) {
return LoginMainState( return LoginMainState(
agreed: agreed ?? this.agreed, agreed: agreed ?? this.agreed,
...@@ -35,6 +34,15 @@ class LoginMainState extends Equatable { ...@@ -35,6 +34,15 @@ class LoginMainState extends Equatable {
loading: loading ?? this.loading, loading: loading ?? this.loading,
); );
} }
@override
List<Object?> get props => [
agreed,
showAgreed,
loading,
showSnackBar,
snackBarMsg,
];
} }
class LoginMainCubit extends Cubit<LoginMainState> { class LoginMainCubit extends Cubit<LoginMainState> {
...@@ -67,12 +75,14 @@ class LoginMainCubit extends Cubit<LoginMainState> { ...@@ -67,12 +75,14 @@ class LoginMainCubit extends Cubit<LoginMainState> {
return; return;
} }
var result = await _fluwx.authBy( var authResult = await _fluwx.authBy(
which: NormalAuth(scope: 'snsapi_userinfo', state: 'wechat_sdk_test'), which: NormalAuth(scope: 'snsapi_userinfo', state: 'wechat_sdk_test'),
); );
if (!result) { if (!authResult) {
throw Exception('微信授权处理失败'); emit(state.copyWith(showSnackBar: true, snackBarMsg: '微信授权处理失败'));
emit(state.copyWith(showSnackBar: false));
return;
} }
// 控制显示加载框 // 控制显示加载框
...@@ -94,20 +104,39 @@ class LoginMainCubit extends Cubit<LoginMainState> { ...@@ -94,20 +104,39 @@ class LoginMainCubit extends Cubit<LoginMainState> {
return; return;
} }
dynamic resultData = await _wechatAuthRepository.codeToSk(response.code!); var resultData = await _wechatAuthRepository.codeToSk(response.code!) as Map<String, dynamic>?;
// 后续添加错误处理
if (resultData['resultCode'] != '001') { // 请求接口异常
if (resultData == null) {
emit(state.copyWith(loading: false, showSnackBar: true, snackBarMsg: '登录请求处理失败'));
emit(state.copyWith(showSnackBar: false));
return; return;
} }
var data = resultData['data']; // 状态码错误
var role = data['roles'][0]; if (resultData['resultCode'] != '001') {
emit(state.copyWith(loading: false, showSnackBar: true, snackBarMsg: '登录请求状态失败'));
emit(state.copyWith(showSnackBar: false));
return;
}
final sessionCode = data['sessionCode']; var data = resultData['data'] as Map<String, dynamic>;
final userCode = data['userCode']; var roles = data['roles'];
var classCode = role['classCode']; // 过滤出家长角色的数据
var userType = role['userType']; roles.removeWhere((element) => element['userType'] != 2);
var stuId = role['stuId'];
var sessionCode = data['sessionCode'];
var userCode = data['userCode'];
var classCode = '';
var userType = 0;
var stuId = '';
if (roles.isNotEmpty) {
var role = roles[0];
classCode = role['classCode'];
userType = role['userType'];
stuId = role['stuId'];
}
var sharedPreferences = getIt.get<SharedPreferences>(); var sharedPreferences = getIt.get<SharedPreferences>();
var preUserCode = sharedPreferences.getString('pre_userCode') ?? ''; var preUserCode = sharedPreferences.getString('pre_userCode') ?? '';
...@@ -116,19 +145,34 @@ class LoginMainCubit extends Cubit<LoginMainState> { ...@@ -116,19 +145,34 @@ class LoginMainCubit extends Cubit<LoginMainState> {
sharedPreferences.setString('pre_userCode', userCode); sharedPreferences.setString('pre_userCode', userCode);
sharedPreferences.setString('pre_classCode', classCode); sharedPreferences.setString('pre_classCode', classCode);
sharedPreferences.setInt('pre_userType', userType); sharedPreferences.setInt('pre_userType', userType);
sharedPreferences.setString('pre_stuId', stuId ?? ''); sharedPreferences.setString('pre_stuId', stuId);
} else { } else {
// 前一个登录用户重新登录 // 前一个登录用户重新登录
classCode = sharedPreferences.getString('pre_classCode'); var preClassCode = sharedPreferences.getString('pre_classCode') ?? '';
userType = sharedPreferences.getInt('pre_userType'); var preUserType = sharedPreferences.getInt('pre_userType') ?? 0;
stuId = sharedPreferences.getString('pre_stuId'); var preStuId = sharedPreferences.getString('pre_stuId') ?? '';
if (preClassCode != '' &&
roles.any((element) =>
element['classCode'] == preClassCode &&
element['userType'] == preUserType &&
element['stuId'] == preStuId)) {
classCode = preClassCode;
userType = preUserType;
stuId = preStuId;
} else {
sharedPreferences.setString('pre_userCode', userCode);
sharedPreferences.setString('pre_classCode', classCode);
sharedPreferences.setInt('pre_userType', userType);
sharedPreferences.setString('pre_stuId', stuId);
}
} }
sharedPreferences.setString('auth_sessionCode', sessionCode); sharedPreferences.setString('auth_sessionCode', sessionCode);
sharedPreferences.setString('auth_userCode', userCode); sharedPreferences.setString('auth_userCode', userCode);
sharedPreferences.setString('auth_classCode', classCode); sharedPreferences.setString('auth_classCode', classCode);
sharedPreferences.setInt('auth_userType', userType); sharedPreferences.setInt('auth_userType', userType);
sharedPreferences.setString('auth_stuId', stuId ?? ''); sharedPreferences.setString('auth_stuId', stuId);
router.go( router.go(
'/web', '/web',
......
...@@ -140,21 +140,35 @@ class LoginPhoneCubit extends Cubit<LoginPhoneState> { ...@@ -140,21 +140,35 @@ class LoginPhoneCubit extends Cubit<LoginPhoneState> {
return; return;
} }
var result = await _phoneAuthRepository.login(phone, verifyCode); var resultData = await _phoneAuthRepository.login(phone, verifyCode);
if (result['code'] != 0) { if (resultData == null) {
emit(state.copyWith(showSnackBar: true, snackBarMsg: result['error'])); emit(state.copyWith(showSnackBar: true, snackBarMsg: '登录请求失败'));
emit(state.copyWith(showSnackBar: false));
return;
}
if (resultData['code'] != 0) {
emit(state.copyWith(showSnackBar: true, snackBarMsg: resultData['error']));
emit(state.copyWith(showSnackBar: false)); emit(state.copyWith(showSnackBar: false));
return; return;
} }
var data = result['data']; var data = resultData['data'] as Map<String, dynamic>;
var role = data['roles'][0]; var roles = data['roles'];
// 过滤出家长角色的数据
final sessionCode = data['sessionCode']; roles.removeWhere((element) => element['userType'] != 2);
final userCode = data['userCode'];
var classCode = role['classCode']; var sessionCode = data['sessionCode'];
var userType = role['userType']; var userCode = data['userCode'];
var stuId = role['stuId']; var classCode = '';
var userType = 0;
var stuId = '';
if (roles.isNotEmpty) {
var role = roles[0];
classCode = role['classCode'];
userType = role['userType'];
stuId = role['stuId'];
}
var sharedPreferences = getIt.get<SharedPreferences>(); var sharedPreferences = getIt.get<SharedPreferences>();
var preUserCode = sharedPreferences.getString('pre_userCode') ?? ''; var preUserCode = sharedPreferences.getString('pre_userCode') ?? '';
...@@ -163,19 +177,34 @@ class LoginPhoneCubit extends Cubit<LoginPhoneState> { ...@@ -163,19 +177,34 @@ class LoginPhoneCubit extends Cubit<LoginPhoneState> {
sharedPreferences.setString('pre_userCode', userCode); sharedPreferences.setString('pre_userCode', userCode);
sharedPreferences.setString('pre_classCode', classCode); sharedPreferences.setString('pre_classCode', classCode);
sharedPreferences.setInt('pre_userType', userType); sharedPreferences.setInt('pre_userType', userType);
sharedPreferences.setString('pre_stuId', stuId ?? ''); sharedPreferences.setString('pre_stuId', stuId);
} else { } else {
// 前一个登录用户重新登录 // 前一个登录用户重新登录
classCode = sharedPreferences.getString('pre_classCode'); var preClassCode = sharedPreferences.getString('pre_classCode') ?? '';
userType = sharedPreferences.getInt('pre_userType'); var preUserType = sharedPreferences.getInt('pre_userType') ?? 0;
stuId = sharedPreferences.getString('pre_stuId'); var preStuId = sharedPreferences.getString('pre_stuId') ?? '';
if (preClassCode != '' &&
roles.any((element) =>
element['classCode'] == preClassCode &&
element['userType'] == preUserType &&
element['stuId'] == preStuId)) {
classCode = preClassCode;
userType = preUserType;
stuId = preStuId;
} else {
sharedPreferences.setString('pre_userCode', userCode);
sharedPreferences.setString('pre_classCode', classCode);
sharedPreferences.setInt('pre_userType', userType);
sharedPreferences.setString('pre_stuId', stuId);
}
} }
sharedPreferences.setString('auth_sessionCode', sessionCode); sharedPreferences.setString('auth_sessionCode', sessionCode);
sharedPreferences.setString('auth_userCode', userCode); sharedPreferences.setString('auth_userCode', userCode);
sharedPreferences.setString('auth_classCode', classCode); sharedPreferences.setString('auth_classCode', classCode);
sharedPreferences.setInt('auth_userType', userType); sharedPreferences.setInt('auth_userType', userType);
sharedPreferences.setString('auth_stuId', stuId ?? ''); sharedPreferences.setString('auth_stuId', stuId);
router.go( router.go(
'/web', '/web',
...@@ -215,13 +244,13 @@ class LoginPhoneCubit extends Cubit<LoginPhoneState> { ...@@ -215,13 +244,13 @@ class LoginPhoneCubit extends Cubit<LoginPhoneState> {
try { try {
_phoneController.dispose(); _phoneController.dispose();
} catch (e) { } catch (e) {
print(e); debugPrint('Error disposing controller: $e');
} }
try { try {
_codeController.dispose(); _codeController.dispose();
} catch (e) { } catch (e) {
print(e); debugPrint('Error disposing controller: $e');
} }
await super.close(); await super.close();
......
...@@ -15,31 +15,41 @@ class LoginQrState extends Equatable { ...@@ -15,31 +15,41 @@ class LoginQrState extends Equatable {
final int status; final int status;
final Uint8List? image; final Uint8List? image;
final String tip; final String tip;
final bool showSnackBar;
final String snackBarMsg;
const LoginQrState({ const LoginQrState({
this.status = 0, this.status = 0,
this.image, this.image,
this.tip = '', this.tip = '',
this.showSnackBar = false,
this.snackBarMsg = '',
}); });
@override
List<Object?> get props => [
status,
image,
tip,
];
LoginQrState copyWith({ LoginQrState copyWith({
int? status, int? status,
Uint8List? image, Uint8List? image,
String? tip, String? tip,
bool? showSnackBar,
String? snackBarMsg,
}) { }) {
return LoginQrState( return LoginQrState(
status: status ?? this.status, status: status ?? this.status,
image: image ?? this.image, image: image ?? this.image,
tip: tip ?? this.tip, tip: tip ?? this.tip,
showSnackBar: showSnackBar ?? this.showSnackBar,
snackBarMsg: snackBarMsg ?? this.snackBarMsg,
); );
} }
@override
List<Object?> get props => [
status,
image,
tip,
showSnackBar,
snackBarMsg,
];
} }
class LoginQrCubit extends Cubit<LoginQrState> { class LoginQrCubit extends Cubit<LoginQrState> {
...@@ -57,13 +67,22 @@ class LoginQrCubit extends Cubit<LoginQrState> { ...@@ -57,13 +67,22 @@ class LoginQrCubit extends Cubit<LoginQrState> {
Future<void> init() async { Future<void> init() async {
// sdk_ticket // sdk_ticket
var result = await _wechatAuthRepository.getTicket(); var resultData = await _wechatAuthRepository.getTicket() as Map<String, dynamic>?;
// 后续添加错误处理 // 请求接口异常
if (result['resultCode'] != '001') { if (resultData == null) {
emit(state.copyWith(showSnackBar: true, snackBarMsg: '生成二维码失败'));
emit(state.copyWith(showSnackBar: false));
return; return;
} }
var sdkTicket = result['data']; // 状态码错误
if (resultData['resultCode'] != '001') {
emit(state.copyWith(showSnackBar: true, snackBarMsg: '生成二维码状态错误'));
emit(state.copyWith(showSnackBar: false));
return;
}
var sdkTicket = resultData['data'];
// 当前时间戳 // 当前时间戳
var timestamp = DateTime.now().millisecondsSinceEpoch; var timestamp = DateTime.now().millisecondsSinceEpoch;
...@@ -78,7 +97,12 @@ class LoginQrCubit extends Cubit<LoginQrState> { ...@@ -78,7 +97,12 @@ class LoginQrCubit extends Cubit<LoginQrState> {
signature: signature, signature: signature,
), ),
); );
print('AuthResult $authResult');
if (!authResult) {
emit(state.copyWith(showSnackBar: true, snackBarMsg: '请求微信失败'));
emit(state.copyWith(showSnackBar: false));
return;
}
} }
void _responseListener(WeChatResponse response) async { void _responseListener(WeChatResponse response) async {
...@@ -122,20 +146,39 @@ class LoginQrCubit extends Cubit<LoginQrState> { ...@@ -122,20 +146,39 @@ class LoginQrCubit extends Cubit<LoginQrState> {
} }
Future<void> _doLogin(String code) async { Future<void> _doLogin(String code) async {
dynamic resultData = await _wechatAuthRepository.codeToSk(code); var resultData = await _wechatAuthRepository.codeToSk(code) as Map<String, dynamic>?;
// 后续添加错误处理
if (resultData['resultCode'] != '001') { // 请求接口异常
if (resultData == null) {
emit(state.copyWith(showSnackBar: true, snackBarMsg: '登录请求处理失败'));
emit(state.copyWith(showSnackBar: false));
return; return;
} }
var data = resultData['data']; // 状态码错误
var role = data['roles'][0]; if (resultData['resultCode'] != '001') {
emit(state.copyWith(showSnackBar: true, snackBarMsg: '登录请求状态失败'));
emit(state.copyWith(showSnackBar: false));
return;
}
final sessionCode = data['sessionCode']; var data = resultData['data'] as Map<String, dynamic>;
final userCode = data['userCode']; var roles = data['roles'];
var classCode = role['classCode']; // 过滤出家长角色的数据
var userType = role['userType']; roles.removeWhere((element) => element['userType'] != 2);
var stuId = role['stuId'];
var sessionCode = data['sessionCode'];
var userCode = data['userCode'];
var classCode = '';
var userType = 0;
var stuId = '';
if (roles.isNotEmpty) {
var role = roles[0];
classCode = role['classCode'];
userType = role['userType'];
stuId = role['stuId'];
}
var sharedPreferences = getIt.get<SharedPreferences>(); var sharedPreferences = getIt.get<SharedPreferences>();
var preUserCode = sharedPreferences.getString('pre_userCode') ?? ''; var preUserCode = sharedPreferences.getString('pre_userCode') ?? '';
...@@ -144,19 +187,34 @@ class LoginQrCubit extends Cubit<LoginQrState> { ...@@ -144,19 +187,34 @@ class LoginQrCubit extends Cubit<LoginQrState> {
sharedPreferences.setString('pre_userCode', userCode); sharedPreferences.setString('pre_userCode', userCode);
sharedPreferences.setString('pre_classCode', classCode); sharedPreferences.setString('pre_classCode', classCode);
sharedPreferences.setInt('pre_userType', userType); sharedPreferences.setInt('pre_userType', userType);
sharedPreferences.setString('pre_stuId', stuId ?? ''); sharedPreferences.setString('pre_stuId', stuId);
} else { } else {
// 前一个登录用户重新登录 // 前一个登录用户重新登录
classCode = sharedPreferences.getString('pre_classCode'); var preClassCode = sharedPreferences.getString('pre_classCode') ?? '';
userType = sharedPreferences.getInt('pre_userType'); var preUserType = sharedPreferences.getInt('pre_userType') ?? 0;
stuId = sharedPreferences.getString('pre_stuId'); var preStuId = sharedPreferences.getString('pre_stuId') ?? '';
if (preClassCode != '' &&
roles.any((element) =>
element['classCode'] == preClassCode &&
element['userType'] == preUserType &&
element['stuId'] == preStuId)) {
classCode = preClassCode;
userType = preUserType;
stuId = preStuId;
} else {
sharedPreferences.setString('pre_userCode', userCode);
sharedPreferences.setString('pre_classCode', classCode);
sharedPreferences.setInt('pre_userType', userType);
sharedPreferences.setString('pre_stuId', stuId);
}
} }
sharedPreferences.setString('auth_sessionCode', sessionCode); sharedPreferences.setString('auth_sessionCode', sessionCode);
sharedPreferences.setString('auth_userCode', userCode); sharedPreferences.setString('auth_userCode', userCode);
sharedPreferences.setString('auth_classCode', classCode); sharedPreferences.setString('auth_classCode', classCode);
sharedPreferences.setInt('auth_userType', userType); sharedPreferences.setInt('auth_userType', userType);
sharedPreferences.setString('auth_stuId', stuId ?? ''); sharedPreferences.setString('auth_stuId', stuId);
router.go( router.go(
'/web', '/web',
......
...@@ -84,6 +84,6 @@ class PhoneAuthRepository { ...@@ -84,6 +84,6 @@ class PhoneAuthRepository {
"verifyCode": verifyCode, "verifyCode": verifyCode,
}, },
); );
return resp.data; return resp.statusCode == 200 ? resp.data : null;
} }
} }
import 'package:appframe/config/locator.dart'; import 'package:appframe/config/locator.dart';
import 'package:appframe/services/api_service.dart'; import 'package:appframe/services/api_service.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
class WechatAuthRepository { class WechatAuthRepository {
late final ApiService _apiService; late final ApiService _apiService;
...@@ -18,9 +19,9 @@ class WechatAuthRepository { ...@@ -18,9 +19,9 @@ class WechatAuthRepository {
}, },
); );
print('登录结果: $resp'); debugPrint('登录结果: $resp');
return resp.data; return resp.statusCode == 200 ? resp.data : null;
} }
Future<dynamic> getTicket() async { Future<dynamic> getTicket() async {
...@@ -32,8 +33,8 @@ class WechatAuthRepository { ...@@ -32,8 +33,8 @@ class WechatAuthRepository {
}, },
); );
print('获取ticket: $resp'); debugPrint('获取ticket: $resp');
return resp.data; return resp.statusCode == 200 ? resp.data : null;
} }
} }
import 'package:appframe/bloc/login_main_cubit.dart'; import 'package:appframe/bloc/login_main_cubit.dart';
import 'package:appframe/config/locator.dart'; import 'package:appframe/config/locator.dart';
import 'package:appframe/ui/widgets/login/login_page_agreed_widget.dart'; import 'package:appframe/ui/widgets/login/login_page_agreed_widget.dart';
import 'package:appframe/ui/widgets/tip_overlay_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fluwx/fluwx.dart'; import 'package:fluwx/fluwx.dart';
...@@ -47,6 +48,7 @@ class LoginMainPage extends StatelessWidget { ...@@ -47,6 +48,7 @@ class LoginMainPage extends StatelessWidget {
if (await getIt.get<Fluwx>().isWeChatInstalled) { if (await getIt.get<Fluwx>().isWeChatInstalled) {
loginMainCubit.wechatAuth(); loginMainCubit.wechatAuth();
} else { } else {
if (!context.mounted) return;
_showWechatNotInstallDialog(context); _showWechatNotInstallDialog(context);
} }
}, },
...@@ -130,6 +132,8 @@ class LoginMainPage extends StatelessWidget { ...@@ -130,6 +132,8 @@ class LoginMainPage extends StatelessWidget {
listener: (context, state) { listener: (context, state) {
if (state.showAgreed) { if (state.showAgreed) {
_showAgreementDialog(context, context.read<LoginMainCubit>()); _showAgreementDialog(context, context.read<LoginMainCubit>());
} else if (state.showSnackBar) {
TipOverlayUtil.showTip(context, state.snackBarMsg);
} }
}, },
), ),
......
import 'package:appframe/bloc/login_phone_cubit.dart'; import 'package:appframe/bloc/login_phone_cubit.dart';
import 'package:appframe/ui/widgets/login/login_page_agreed_widget.dart'; import 'package:appframe/ui/widgets/login/login_page_agreed_widget.dart';
import 'package:appframe/ui/widgets/tip_overlay_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
...@@ -79,7 +80,7 @@ class LoginPhonePage extends StatelessWidget { ...@@ -79,7 +80,7 @@ class LoginPhonePage extends StatelessWidget {
if (state.showAgreed) { if (state.showAgreed) {
_showAgreementDialog(context, context.read<LoginPhoneCubit>()); _showAgreementDialog(context, context.read<LoginPhoneCubit>());
} else if (state.showSnackBar) { } else if (state.showSnackBar) {
_showTip(context, state.snackBarMsg); TipOverlayUtil.showTip(context, state.snackBarMsg);
} }
}, },
), ),
...@@ -381,34 +382,4 @@ class LoginPhonePage extends StatelessWidget { ...@@ -381,34 +382,4 @@ class LoginPhonePage extends StatelessWidget {
loginPhoneCubit.cancelAgreed(); loginPhoneCubit.cancelAgreed();
} }
} }
void _showTip(BuildContext context, String tip) {
OverlayEntry overlayEntry = OverlayEntry(
builder: (context) => Positioned(
top: 200,
left: 20,
right: 20,
child: Material(
color: Colors.transparent,
child: Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.black54,
borderRadius: BorderRadius.circular(8),
),
child: Text(
tip,
style: TextStyle(color: Colors.white),
textAlign: TextAlign.center,
),
),
),
),
);
Overlay.of(context).insert(overlayEntry);
Future.delayed(Duration(seconds: 2), () {
overlayEntry.remove();
});
}
} }
import 'package:appframe/bloc/login_qr_cubit.dart'; import 'package:appframe/bloc/login_qr_cubit.dart';
import 'package:appframe/ui/widgets/tip_overlay_widget.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
...@@ -60,7 +61,11 @@ class LoginQrPage extends StatelessWidget { ...@@ -60,7 +61,11 @@ class LoginQrPage extends StatelessWidget {
), ),
); );
}, },
listener: (context, state) {}, listener: (context, state) {
if (state.showSnackBar) {
TipOverlayUtil.showTip(context, state.snackBarMsg);
}
},
)); ));
} }
......
import 'package:flutter/material.dart';
class TipOverlayUtil {
static void showTip(BuildContext context, String tip) {
OverlayEntry overlayEntry = OverlayEntry(
builder: (context) => Positioned(
top: 200,
left: 20,
right: 20,
child: Material(
color: Colors.transparent,
child: Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.black54,
borderRadius: BorderRadius.circular(8),
),
child: Text(
tip,
style: TextStyle(color: Colors.white),
textAlign: TextAlign.center,
),
),
),
),
);
Overlay.of(context).insert(overlayEntry);
Future.delayed(Duration(seconds: 2), () {
overlayEntry.remove();
});
}
}
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!