From 10456accec142f0d8e9e7a8e583b06d461e5c8a9 Mon Sep 17 00:00:00 2001 From: htylight Date: Tue, 4 Jul 2023 11:51:11 +0800 Subject: [PATCH] implement signin and signup --- lib/request/server.dart | 36 ++++ lib/request/signin_signup.dart | 11 - lib/request/signup_signin.dart | 55 +++++ lib/response_model/base.dart | 10 + .../components/common_widgets.dart | 61 +++++- .../components/email_signin.dart | 4 +- .../signin_signup/components/signup.dart | 150 ++++++++++---- .../components/username_signin.dart | 67 +++--- pubspec.lock | 192 +++++++++--------- pubspec.yaml | 2 + 10 files changed, 416 insertions(+), 172 deletions(-) create mode 100644 lib/request/server.dart delete mode 100644 lib/request/signin_signup.dart create mode 100644 lib/request/signup_signin.dart create mode 100644 lib/response_model/base.dart diff --git a/lib/request/server.dart b/lib/request/server.dart new file mode 100644 index 0000000..1d1cd29 --- /dev/null +++ b/lib/request/server.dart @@ -0,0 +1,36 @@ +import 'package:dio/dio.dart'; + +final baseOptions = BaseOptions( + baseUrl: 'http://10.0.2.2:8000/api', + connectTimeout: const Duration(seconds: 5), + receiveTimeout: const Duration(seconds: 5), +); + +var request = Dio(baseOptions) + ..interceptors.add( + InterceptorsWrapper( + onRequest: (RequestOptions options, RequestInterceptorHandler handler) { + String baseUrl = options.baseUrl.replaceFirst('/api', ''); + options.baseUrl = baseUrl; + return handler.next(options); + }, + onResponse: (Response response, ResponseInterceptorHandler handler) { + if (response.statusCode! >= 200 && response.statusCode! < 400) { + return handler.resolve(response); + } else { + handler.reject( + DioException.badResponse( + statusCode: response.statusCode!, + requestOptions: RequestOptions(), + response: response, + ), + ); + } + }, + onError: (DioException e, ErrorInterceptorHandler handler) { + // print('错误信息:' + e.response?.data); + // print('错误码: ${e.response?.statusCode}'); + handler.reject(e); + }, + ), + ); diff --git a/lib/request/signin_signup.dart b/lib/request/signin_signup.dart deleted file mode 100644 index 958b57f..0000000 --- a/lib/request/signin_signup.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'dart:convert'; - -import 'package:http/http.dart' as http; - -Future> signup() async { - final http.Response response = await http - .get(Uri.parse('http://10.0.2.2:8000/await')) - .timeout(const Duration(seconds: 5)); - String body = response.body; - return jsonDecode(body); -} diff --git a/lib/request/signup_signin.dart b/lib/request/signup_signin.dart new file mode 100644 index 0000000..dd6d587 --- /dev/null +++ b/lib/request/signup_signin.dart @@ -0,0 +1,55 @@ +import 'package:dio/dio.dart'; +import 'package:together_mobile/response_model/base.dart'; + +import 'server.dart'; + +Future hasAccountExisted( + String condition, String value) async { + Response response = await request.get( + '/signup/has_existed', + queryParameters: { + 'condition': condition, + 'value': value, + }, + ); + return BaseResponseModel.fromJson(response.data); +} + +Future askCode(String email) async { + await request.get('/signup/code/$email'); +} + +Future signup( + String username, + String password, + String email, + String code, +) async { + Response response = await request.post( + '/signup', + data: { + 'username': username, + 'password': password, + 'email': email, + 'code': code, + }, + ); + + return BaseResponseModel.fromJson(response.data); +} + +Future signinByUsername( + String username, String password) async { + final formData = FormData.fromMap({ + 'username': username, + 'password': password, + }); + + Response response = await request.post( + '/signin/token/username', + data: formData, + ); + + + return BaseResponseModel.fromJson(response.data); +} diff --git a/lib/response_model/base.dart b/lib/response_model/base.dart new file mode 100644 index 0000000..c7e3a2c --- /dev/null +++ b/lib/response_model/base.dart @@ -0,0 +1,10 @@ +class BaseResponseModel { + late final int code; + late final String msg; + + BaseResponseModel.fromJson(Map json) { + code = json['code']; + msg = json['msg']; + } +} + diff --git a/lib/screens/signin_signup/components/common_widgets.dart b/lib/screens/signin_signup/components/common_widgets.dart index 214a3c1..f282b48 100644 --- a/lib/screens/signin_signup/components/common_widgets.dart +++ b/lib/screens/signin_signup/components/common_widgets.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:together_mobile/common/constants.dart'; +import 'package:together_mobile/request/signup_signin.dart'; +import 'package:together_mobile/response_model/base.dart'; class SignTextField extends StatefulWidget { const SignTextField({ @@ -8,6 +10,7 @@ class SignTextField extends StatefulWidget { this.color = kPrimaryColor, this.obscureText = false, required this.type, + this.isSignup = true, required this.labelText, required this.controller, required this.isError, @@ -16,6 +19,7 @@ class SignTextField extends StatefulWidget { final Color color; final bool obscureText; final String type; + final bool isSignup; final String labelText; final TextEditingController controller; final void Function(String, bool) isError; @@ -27,6 +31,53 @@ class SignTextField extends StatefulWidget { class _SignTextFieldState extends State { int _length = 0; String? _errorText; + FocusNode? _node; + + @override + void initState() { + super.initState(); + if (widget.isSignup) { + _node = FocusNode(); + _node!.addListener(_handleFocusChange); + } + } + + void _handleFocusChange() async { + if (!widget.isSignup) { + return; + } + + switch (widget.type) { + case 'username' || 'email': + if (!_node!.hasFocus) { + if (widget.controller.text.isNotEmpty && _errorText == null) { + BaseResponseModel res = + await hasAccountExisted(widget.type, widget.controller.text); + if (widget.type == 'username') { + setState(() { + res.code == 10100 ? _errorText = null : _errorText = '用户名已存在'; + }); + } else { + setState(() { + res.code == 10100 ? _errorText = null : _errorText = '邮箱已被使用'; + }); + } + } + } + + default: + null; + } + } + + @override + void dispose() { + if (widget.isSignup) { + _node!.removeListener(_handleFocusChange); + _node!.dispose(); + } + super.dispose(); + } @override Widget build(BuildContext context) { @@ -37,11 +88,13 @@ class _SignTextFieldState extends State { }); setErrorText(); widget.isError( - widget.type, - (_errorText == null && widget.controller.text.isEmpty) || - _errorText != null); + widget.type, + (_errorText == null && widget.controller.text.isEmpty) || + _errorText != null, + ); }, controller: widget.controller, + focusNode: _node, obscureText: widget.obscureText, cursorColor: widget.color, textAlignVertical: TextAlignVertical.bottom, @@ -93,7 +146,7 @@ class _SignTextFieldState extends State { } break; - case 'password' || 'password1' || 'password2': + case 'password': if (widget.controller.text.contains(RegExp(r'\s'))) { setState(() { _errorText = '密码不能包含空格'; diff --git a/lib/screens/signin_signup/components/email_signin.dart b/lib/screens/signin_signup/components/email_signin.dart index d30efc1..cde53bb 100644 --- a/lib/screens/signin_signup/components/email_signin.dart +++ b/lib/screens/signin_signup/components/email_signin.dart @@ -4,7 +4,7 @@ import 'package:cherry_toast/cherry_toast.dart'; import 'common_widgets.dart'; import 'package:together_mobile/common/constants.dart'; -import 'package:together_mobile/request/signin_signup.dart'; +import 'package:together_mobile/request/signup_signin.dart'; class EmailSigninBody extends StatefulWidget { const EmailSigninBody({super.key}); @@ -118,7 +118,7 @@ class _EmailSigninBodyState extends State { if (_isProgressShow && !_isHttpSend) { _isHttpSend = true; - result = await signup(); + // result = await signup(); } setState(() { diff --git a/lib/screens/signin_signup/components/signup.dart b/lib/screens/signin_signup/components/signup.dart index 5682d3d..8897820 100644 --- a/lib/screens/signin_signup/components/signup.dart +++ b/lib/screens/signin_signup/components/signup.dart @@ -1,10 +1,14 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:cherry_toast/cherry_toast.dart'; +import 'package:http/http.dart'; +import 'package:together_mobile/response_model/base.dart'; import 'common_widgets.dart'; import 'package:together_mobile/common/constants.dart'; -import 'package:together_mobile/request/signin_signup.dart'; +import 'package:together_mobile/request/signup_signin.dart' as signup_request; class SignupBody extends StatefulWidget { const SignupBody({super.key}); @@ -19,21 +23,32 @@ class _SignupBodyState extends State { final TextEditingController usernameController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); - final TextEditingController phoneEmailController = TextEditingController(); + final TextEditingController emailController = TextEditingController(); final TextEditingController codeController = TextEditingController(); final Map _isError = { 'username': false, - 'password1': false, - 'password2': false, + 'password': false, + 'email': false, + 'code': false, }; + int _count = 60; + bool _isGetCode = false; + void _isInputError(String type, bool error) { setState(() { _isError[type] = error; }); } + @override + void dispose() { + usernameController.dispose(); + passwordController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Column( @@ -69,7 +84,7 @@ class _SignupBodyState extends State { color: kSecondaryColor, obscureText: true, labelText: '密码', - type: 'password1', + type: 'password', controller: passwordController, isError: _isInputError, ), @@ -77,7 +92,7 @@ class _SignupBodyState extends State { SizedBox( width: 250, child: SignTextField( - controller: phoneEmailController, + controller: emailController, color: kSecondaryColor, type: 'email', labelText: '邮箱', @@ -101,14 +116,19 @@ class _SignupBodyState extends State { ), ), TextButton( - onPressed: () {}, + onPressed: () async { + await _getCode(context); + }, style: TextButton.styleFrom( - foregroundColor: kSecondaryColor, - // tapTargetSize: MaterialTapTargetSize.shrinkWrap, + foregroundColor: + _isGetCode ? kUnActivatedColor : kSecondaryColor, ), - child: const Text( - '获取验证码', - style: TextStyle(color: kSecondaryColor, fontSize: 15.0), + child: Text( + _isGetCode ? '已发送($_count)' : '获取验证码', + style: TextStyle( + color: _isGetCode ? kUnActivatedColor : kSecondaryColor, + fontSize: 15.0, + ), ), ), ], @@ -116,7 +136,7 @@ class _SignupBodyState extends State { ), elevatedButton( onPressed: () { - confirm(context); + _confirm(context); }, text: '确定', color: kSecondaryColor, @@ -125,40 +145,102 @@ class _SignupBodyState extends State { ); } - void confirm(BuildContext context) async { - if (_isError['username']! || - _isError['password1']! || - _isError['password2']!) { - CherryToast.error( - title: const Text('账号或密码不符合规范'), - toastDuration: const Duration(seconds: 2), - animationDuration: const Duration(seconds: 1), - ).show(context); + Future _getCode(BuildContext context) async { + if (_isGetCode) { + _showWarningToast(context, '验证码还在有效期内'); + return; + } else if (_isError['email']!) { + _showWarningToast(context, '邮箱格式不正确'); + return; + } else if (emailController.text.isEmpty) { + _showWarningToast(context, '邮箱不能为空'); return; } + await signup_request.askCode(emailController.text); + + setState(() { + _isGetCode = true; + }); + + Timer.periodic(const Duration(seconds: 1), (timer) { + setState(() { + _count--; + }); + + if (_count == 0) { + timer.cancel(); + setState(() { + _isGetCode = false; + _count = 60; + }); + } + }); + } + + void _confirm(BuildContext context) async { + if (_isError['username']! || _isError['password']!) { + _showWarningToast(context, '账号或密码不符合规范'); + return; + } else if (_isError['email']!) { + _showWarningToast(context, '邮箱格式不正确'); + return; + } else if (_isError['code']!) { + _showWarningToast(context, '验证码格式不正确'); + return; + } else if (emailController.text.isEmpty) { + _showWarningToast(context, '邮箱不能为空'); + return; + } else if (codeController.text.isEmpty) { + _showWarningToast(context, '验证码不能为空'); + return; + } else if (usernameController.text.isEmpty) { + _showWarningToast(context, '用户名不能为空'); + return; + } else if (passwordController.text.isEmpty) { + _showWarningToast(context, '密码不能为空'); + return; + } + + late BaseResponseModel res; + setState(() { if (!_isProgressShow) _isProgressShow = true; }); - Map? result; - if (_isProgressShow && !_isHttpSend) { _isHttpSend = true; - result = await signup(); + res = await signup_request.signup( + usernameController.text, + passwordController.text, + emailController.text, + codeController.text, + ); } + setState(() { - if (result!['code'] == 10000) { - _isHttpSend = false; - _isProgressShow = false; - } + _isHttpSend = false; + _isProgressShow = false; }); + + if (res.code == 10100) { + // ignore: use_build_context_synchronously + CherryToast.success( + title: const Text('注册成功!'), + toastDuration: const Duration(seconds: 2), + animationDuration: const Duration(seconds: 1), + ).show(context); + } else if (res.code == 10102) { + // ignore: use_build_context_synchronously + _showWarningToast(context, '验证码错误或已过期'); + } } - @override - void dispose() { - usernameController.dispose(); - passwordController.dispose(); - super.dispose(); + void _showWarningToast(BuildContext context, String text) { + CherryToast.warning( + title: Text(text), + toastDuration: const Duration(seconds: 2), + animationDuration: const Duration(seconds: 1), + ).show(context); } } diff --git a/lib/screens/signin_signup/components/username_signin.dart b/lib/screens/signin_signup/components/username_signin.dart index fc7df9a..73bb363 100644 --- a/lib/screens/signin_signup/components/username_signin.dart +++ b/lib/screens/signin_signup/components/username_signin.dart @@ -2,10 +2,11 @@ import 'package:flutter/material.dart'; import 'package:cherry_toast/cherry_toast.dart'; import 'package:go_router/go_router.dart'; +import 'package:together_mobile/response_model/base.dart'; import 'common_widgets.dart'; import 'package:together_mobile/common/constants.dart'; -import 'package:together_mobile/request/signin_signup.dart'; +import 'package:together_mobile/request/signup_signin.dart'; class UsernameSigninBody extends StatefulWidget { const UsernameSigninBody({super.key}); @@ -15,8 +16,8 @@ class UsernameSigninBody extends StatefulWidget { } class _UsernameSigninBodyState extends State { - final bool _isProgressShow = false; - final bool _isHttpSend = false; + bool _isProgressShow = false; + bool _isHttpSend = false; final TextEditingController usernameController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); @@ -56,6 +57,7 @@ class _UsernameSigninBodyState extends State { child: SignTextField( labelText: '用户名', type: 'username', + isSignup: false, controller: usernameController, isError: _isInputError, ), @@ -69,6 +71,7 @@ class _UsernameSigninBodyState extends State { child: SignTextField( obscureText: true, labelText: '密码', + isSignup: false, type: 'password', controller: passwordController, isError: _isInputError, @@ -80,42 +83,48 @@ class _UsernameSigninBodyState extends State { ), elevatedButton( onPressed: () { - confirm(context); + _signin(context); }, - text: '确定', + text: '登录', ), ], ); } - void confirm(BuildContext context) async { - // if (_isError['username']! || _isError['password']!) { - // CherryToast.error( - // title: const Text('账号或密码不符合规范'), - // toastDuration: const Duration(seconds: 2), - // animationDuration: const Duration(seconds: 1), - // ).show(context); - // return; - // } + void _signin(BuildContext context) async { + if (_isError['username']! || _isError['password']!) { + CherryToast.error( + title: const Text('账号或密码不符合规范'), + toastDuration: const Duration(seconds: 2), + animationDuration: const Duration(seconds: 1), + ).show(context); + return; + } - // setState(() { - // if (!_isProgressShow) _isProgressShow = true; - // }); + setState(() { + if (!_isProgressShow) _isProgressShow = true; + }); - // Map? result; + late BaseResponseModel result; - // if (_isProgressShow && !_isHttpSend) { - // _isHttpSend = true; - // result = await signup(); - // } - // setState(() { - // if (result!['code'] == 10000) { - // _isHttpSend = false; - // _isProgressShow = false; - // } - // }); + if (_isProgressShow && !_isHttpSend) { + _isHttpSend = true; + result = await signinByUsername( + usernameController.text, passwordController.text); + } - context.go('/chat'); + setState(() { + _isHttpSend = false; + _isProgressShow = false; + }); + + if (result.code == 10200) { + // ignore: use_build_context_synchronously + context.go('/chat'); + } else { + // ignore: use_build_context_synchronously + CherryToast.error(title: const Text('用户名或密码错误')).show(context); + } } @override diff --git a/pubspec.lock b/pubspec.lock index a7660d2..f2db1ad 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -6,7 +6,7 @@ packages: description: name: args sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.2" async: @@ -14,7 +14,7 @@ packages: description: name: async sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.11.0" badges: @@ -22,7 +22,7 @@ packages: description: name: badges sha256: "6e7f3ec561ec08f47f912cfe349d4a1707afdc8dda271e17b046aa6d42c89e77" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.1" boolean_selector: @@ -30,7 +30,7 @@ packages: description: name: boolean_selector sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" characters: @@ -38,7 +38,7 @@ packages: description: name: characters sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.0" cherry_toast: @@ -46,7 +46,7 @@ packages: description: name: cherry_toast sha256: a52fe28040cc80490ebaf1dfebaf17f8c7debb4fe5bf6e84d2a57b04b9c04569 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.1" clock: @@ -54,7 +54,7 @@ packages: description: name: clock sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" collection: @@ -62,7 +62,7 @@ packages: description: name: collection sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.17.1" cross_file: @@ -70,7 +70,7 @@ packages: description: name: cross_file sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.3.3+4" crypto: @@ -78,7 +78,7 @@ packages: description: name: crypto sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.3" csslib: @@ -86,7 +86,7 @@ packages: description: name: csslib sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.0" dbus: @@ -94,15 +94,23 @@ packages: description: name: dbus sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.7.8" + dio: + dependency: "direct main" + description: + name: dio + sha256: a9d76e72985d7087eb7c5e7903224ae52b337131518d127c554b9405936752b8 + url: "https://pub.dev" + source: hosted + version: "5.2.1+1" fake_async: dependency: transitive description: name: fake_async sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: @@ -110,7 +118,7 @@ packages: description: name: ffi sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.2" file: @@ -118,41 +126,41 @@ packages: description: name: file sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.1.4" file_selector_linux: dependency: transitive description: name: file_selector_linux - sha256: d17c5e450192cdc40b718804dfb4eaf79a71bed60ee9530703900879ba50baa3 - url: "https://pub.flutter-io.cn" + sha256: "770eb1ab057b5ae4326d1c24cc57710758b9a46026349d021d6311bd27580046" + url: "https://pub.dev" source: hosted - version: "0.9.1+3" + version: "0.9.2" file_selector_macos: dependency: transitive description: name: file_selector_macos - sha256: "6290eec24fc4cc62535fe609e0c6714d3c1306191dc8c3b0319eaecc09423a3a" - url: "https://pub.flutter-io.cn" + sha256: "7a6f1ae6107265664f3f7f89a66074882c4d506aef1441c9af313c1f7e6f41ce" + url: "https://pub.dev" source: hosted - version: "0.9.2" + version: "0.9.3" file_selector_platform_interface: dependency: transitive description: name: file_selector_platform_interface sha256: "412705a646a0ae90f33f37acfae6a0f7cbc02222d6cd34e479421c3e74d3853c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.6.0" file_selector_windows: dependency: transitive description: name: file_selector_windows - sha256: ef246380b66d1fb9089fc65622c387bf3780bca79f533424c31d07f12c2c7fd8 - url: "https://pub.flutter-io.cn" + sha256: "1372760c6b389842b77156203308940558a2817360154084368608413835fc26" + url: "https://pub.dev" source: hosted - version: "0.9.2" + version: "0.9.3" flutter: dependency: "direct main" description: flutter @@ -162,16 +170,16 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c - url: "https://pub.flutter-io.cn" + sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" flutter_local_notifications: dependency: "direct main" description: name: flutter_local_notifications sha256: "812791d43ccfc1b443a0d39fa02a206fc228c597e28ff9337e09e3ca8d370391" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "14.1.1" flutter_local_notifications_linux: @@ -179,7 +187,7 @@ packages: description: name: flutter_local_notifications_linux sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.0+1" flutter_local_notifications_platform_interface: @@ -187,7 +195,7 @@ packages: description: name: flutter_local_notifications_platform_interface sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.0.0+1" flutter_plugin_android_lifecycle: @@ -195,7 +203,7 @@ packages: description: name: flutter_plugin_android_lifecycle sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.15" flutter_slidable: @@ -203,7 +211,7 @@ packages: description: name: flutter_slidable sha256: cc4231579e3eae41ae166660df717f4bad1359c87f4a4322ad8ba1befeb3d2be - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.0" flutter_test: @@ -215,10 +223,10 @@ packages: dependency: "direct main" description: name: flutter_timezone - sha256: "9b179c76cbded894e3208b420d0c4286f6c9ab7178c063eba8bc4266a3ee1a3c" - url: "https://pub.flutter-io.cn" + sha256: "4508018aba499c837f723e2e718259eb677410490638b7ea669b11113d083e68" + url: "https://pub.dev" source: hosted - version: "1.0.6" + version: "1.0.7" flutter_web_plugins: dependency: transitive description: flutter @@ -229,7 +237,7 @@ packages: description: name: go_router sha256: "00d1b67d6e9fa443331da229084dd3eb04407f5a2dff22940bd7bba6af5722c3" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.1.1" google_fonts: @@ -237,7 +245,7 @@ packages: description: name: google_fonts sha256: "6b6f10f0ce3c42f6552d1c70d2c28d764cf22bb487f50f66cca31dcd5194f4d6" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.4" html: @@ -245,7 +253,7 @@ packages: description: name: html sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.15.4" http: @@ -253,7 +261,7 @@ packages: description: name: http sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.13.6" http_parser: @@ -261,7 +269,7 @@ packages: description: name: http_parser sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.2" image_picker: @@ -269,7 +277,7 @@ packages: description: name: image_picker sha256: b6951e25b795d053a6ba03af5f710069c99349de9341af95155d52665cb4607c - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.8.9" image_picker_android: @@ -277,7 +285,7 @@ packages: description: name: image_picker_android sha256: d2bab152deb2547ea6f53d82ebca9b7e77386bb706e5789e815d37e08ea475bb - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.8.7+3" image_picker_for_web: @@ -285,7 +293,7 @@ packages: description: name: image_picker_for_web sha256: "869fe8a64771b7afbc99fc433a5f7be2fea4d1cb3d7c11a48b6b579eb9c797f0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.0" image_picker_ios: @@ -293,7 +301,7 @@ packages: description: name: image_picker_ios sha256: b3e2f21feb28b24dd73a35d7ad6e83f568337c70afab5eabac876e23803f264b - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.8.8" image_picker_linux: @@ -301,7 +309,7 @@ packages: description: name: image_picker_linux sha256: "02cbc21fe1706b97942b575966e5fbbeaac535e76deef70d3a242e4afb857831" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.1" image_picker_macos: @@ -309,7 +317,7 @@ packages: description: name: image_picker_macos sha256: cee2aa86c56780c13af2c77b5f2f72973464db204569e1ba2dd744459a065af4 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.1" image_picker_platform_interface: @@ -317,7 +325,7 @@ packages: description: name: image_picker_platform_interface sha256: "7c7b96bb9413a9c28229e717e6fd1e3edd1cc5569c1778fcca060ecf729b65ee" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.8.0" image_picker_windows: @@ -325,7 +333,7 @@ packages: description: name: image_picker_windows sha256: c3066601ea42113922232c7b7b3330a2d86f029f685bba99d82c30e799914952 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.1" js: @@ -333,7 +341,7 @@ packages: description: name: js sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.6.7" lints: @@ -341,15 +349,15 @@ packages: description: name: lints sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" logging: - dependency: transitive + dependency: "direct main" description: name: logging sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.0" matcher: @@ -357,7 +365,7 @@ packages: description: name: matcher sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.12.15" material_color_utilities: @@ -365,7 +373,7 @@ packages: description: name: material_color_utilities sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.2.0" meta: @@ -373,7 +381,7 @@ packages: description: name: meta sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.9.1" mime: @@ -381,7 +389,7 @@ packages: description: name: mime sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.4" nested: @@ -389,7 +397,7 @@ packages: description: name: nested sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.0" path: @@ -397,7 +405,7 @@ packages: description: name: path sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.8.3" path_provider: @@ -405,7 +413,7 @@ packages: description: name: path_provider sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.15" path_provider_android: @@ -413,7 +421,7 @@ packages: description: name: path_provider_android sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.27" path_provider_foundation: @@ -421,7 +429,7 @@ packages: description: name: path_provider_foundation sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.3" path_provider_linux: @@ -429,7 +437,7 @@ packages: description: name: path_provider_linux sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.11" path_provider_platform_interface: @@ -437,7 +445,7 @@ packages: description: name: path_provider_platform_interface sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.6" path_provider_windows: @@ -445,7 +453,7 @@ packages: description: name: path_provider_windows sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.7" petitparser: @@ -453,7 +461,7 @@ packages: description: name: petitparser sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.4.0" platform: @@ -461,7 +469,7 @@ packages: description: name: platform sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: @@ -469,7 +477,7 @@ packages: description: name: plugin_platform_interface sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.4" process: @@ -477,7 +485,7 @@ packages: description: name: process sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.2.4" provider: @@ -485,7 +493,7 @@ packages: description: name: provider sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.0.5" reorderables: @@ -493,7 +501,7 @@ packages: description: name: reorderables sha256: "004a886e4878df1ee27321831c838bc1c976311f4ca6a74ce7d561e506540a77" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.6.0" sky_engine: @@ -506,7 +514,7 @@ packages: description: name: source_span sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.9.1" stack_trace: @@ -514,7 +522,7 @@ packages: description: name: stack_trace sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.11.0" stream_channel: @@ -522,7 +530,7 @@ packages: description: name: stream_channel sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.1" string_scanner: @@ -530,7 +538,7 @@ packages: description: name: string_scanner sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.0" term_glyph: @@ -538,7 +546,7 @@ packages: description: name: term_glyph sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: @@ -546,7 +554,7 @@ packages: description: name: test_api sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.5.1" timezone: @@ -554,7 +562,7 @@ packages: description: name: timezone sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.9.2" typed_data: @@ -562,7 +570,7 @@ packages: description: name: typed_data sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.3.2" vector_math: @@ -570,23 +578,23 @@ packages: description: name: vector_math sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.4" video_player: dependency: "direct main" description: name: video_player - sha256: de95f0e9405f29b5582573d4166132e71f83b3158aac14e8ee5767a54f4f1fbd - url: "https://pub.flutter-io.cn" + sha256: "3fd106c74da32f336dc7feb65021da9b0207cb3124392935f1552834f7cce822" + url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "2.7.0" video_player_android: dependency: transitive description: name: video_player_android sha256: f338a5a396c845f4632959511cad3542cdf3167e1b2a1a948ef07f7123c03608 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.9" video_player_avfoundation: @@ -594,7 +602,7 @@ packages: description: name: video_player_avfoundation sha256: "4c274e439f349a0ee5cb3c42978393ede173a443b98f50de6ffe6900eaa19216" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.6" video_player_platform_interface: @@ -602,7 +610,7 @@ packages: description: name: video_player_platform_interface sha256: a8c4dcae2a7a6e7cc1d7f9808294d968eca1993af34a98e95b9bdfa959bec684 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.1.0" video_player_web: @@ -610,23 +618,23 @@ packages: description: name: video_player_web sha256: "44ce41424d104dfb7cf6982cc6b84af2b007a24d126406025bf40de5d481c74c" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.16" win32: dependency: transitive description: name: win32 - sha256: "1414f27dd781737e51afa9711f2ac2ace6ab4498ee98e20863fa5505aa00c58c" - url: "https://pub.flutter-io.cn" + sha256: dfdf0136e0aa7a1b474ea133e67cb0154a0acd2599c4f3ada3b49d38d38793ee + url: "https://pub.dev" source: hosted - version: "5.0.4" + version: "5.0.5" xdg_directories: dependency: transitive description: name: xdg_directories sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.0.0" xml: @@ -634,7 +642,7 @@ packages: description: name: xml sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.3.0" sdks: diff --git a/pubspec.yaml b/pubspec.yaml index 54a8f6a..c7b47d9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,7 @@ environment: dependencies: badges: ^3.1.1 cherry_toast: ^1.2.1 + dio: ^5.2.1+1 flutter: sdk: flutter flutter_local_notifications: ^14.1.1 @@ -39,6 +40,7 @@ dependencies: google_fonts: ^4.0.0 http: ^0.13.0 image_picker: ^0.8.7+5 + logging: ^1.2.0 provider: ^6.0.5 reorderables: ^0.6.0 timezone: ^0.9.2