助记词校验,登录
This commit is contained in:
@@ -1,9 +1,12 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="site.zhchain.chat">
|
package="site.zhchain.chat">
|
||||||
<application
|
<application
|
||||||
android:label="ZH-CHAT"
|
android:label="ZH-CHAT"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:requestLegacyExternalStorage="true"
|
||||||
|
tools:replace="android:label">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|||||||
BIN
assets/images/login_bg.png
Normal file
BIN
assets/images/login_bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -3,6 +3,7 @@ import 'package:chat/configs/themes.dart';
|
|||||||
import 'package:chat/controllers/group_controller.dart';
|
import 'package:chat/controllers/group_controller.dart';
|
||||||
import 'package:chat/controllers/moment_controller.dart';
|
import 'package:chat/controllers/moment_controller.dart';
|
||||||
import 'package:chat/controllers/private_controller.dart';
|
import 'package:chat/controllers/private_controller.dart';
|
||||||
|
import 'package:chat/controllers/publish_controller.dart';
|
||||||
import 'package:chat/controllers/user_controller.dart';
|
import 'package:chat/controllers/user_controller.dart';
|
||||||
import 'package:chat/routes/app_router.dart';
|
import 'package:chat/routes/app_router.dart';
|
||||||
import 'package:chat/routes/app_routes.dart';
|
import 'package:chat/routes/app_routes.dart';
|
||||||
@@ -66,6 +67,10 @@ class MyApp extends StatelessWidget {
|
|||||||
() => UserController(),
|
() => UserController(),
|
||||||
fenix: true,
|
fenix: true,
|
||||||
);
|
);
|
||||||
|
Get.lazyPut(
|
||||||
|
() => PublishController(),
|
||||||
|
fenix: true,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import 'package:chat/models/user_info_model.dart';
|
import 'package:chat/models/user_info_model.dart';
|
||||||
|
|
||||||
class AuthModel {
|
class AuthModel {
|
||||||
String accessToken;
|
String userToken;
|
||||||
String userSig;
|
String userSig;
|
||||||
String userID;
|
String userID;
|
||||||
UserInfoModel userInfo;
|
UserInfoModel userInfo;
|
||||||
|
|
||||||
AuthModel({
|
AuthModel({
|
||||||
required this.accessToken,
|
required this.userToken,
|
||||||
required this.userID,
|
required this.userID,
|
||||||
required this.userSig,
|
required this.userSig,
|
||||||
required this.userInfo,
|
required this.userInfo,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory AuthModel.fromJson(Map<String, dynamic> json) => AuthModel(
|
factory AuthModel.fromJson(Map<String, dynamic> json) => AuthModel(
|
||||||
accessToken: json['access_token'],
|
userToken: json['access_token'],
|
||||||
userID: json['user_id'].toString(),
|
userID: json['user_id'].toString(),
|
||||||
userSig: json['user_sig'],
|
userSig: json['user_sig'],
|
||||||
userInfo: UserInfoModel.fromJson(json['user_info']),
|
userInfo: UserInfoModel.fromJson(json['user_info']),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:chat/models/user_info_model.dart';
|
|||||||
import 'package:chat/providers/auth_provider.dart';
|
import 'package:chat/providers/auth_provider.dart';
|
||||||
import 'package:chat/routes/auth_routes.dart';
|
import 'package:chat/routes/auth_routes.dart';
|
||||||
import 'package:chat/services/tim_service.dart';
|
import 'package:chat/services/tim_service.dart';
|
||||||
|
import 'package:chat/utils/hd_wallet.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:get_storage/get_storage.dart';
|
import 'package:get_storage/get_storage.dart';
|
||||||
import 'package:tencent_im_sdk_plugin/tencent_im_sdk_plugin.dart';
|
import 'package:tencent_im_sdk_plugin/tencent_im_sdk_plugin.dart';
|
||||||
@@ -44,19 +45,24 @@ class AuthService extends GetxService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> login(String address) async {
|
Future<bool> login(String mnemonic) async {
|
||||||
address = '12dUut3dG5xWi6JPDMjSSK6s2JPcfeKYL1';
|
String? address = HDWallet.mnemonicToAddress(mnemonic);
|
||||||
|
|
||||||
|
if (address == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var result = await AuthProvider.login(address);
|
var result = await AuthProvider.login(address);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
_box.write('userId', result.userID);
|
_box.write('userId', result.userID);
|
||||||
_box.write('userSig', result.userSig);
|
_box.write('userSig', result.userSig);
|
||||||
_box.write('userToken', result.accessToken);
|
_box.write('userToken', result.userToken);
|
||||||
_box.write('userInfo', result.userInfo.toJson());
|
_box.write('userInfo', result.userInfo.toJson());
|
||||||
|
|
||||||
userId = result.userID;
|
userId = result.userID;
|
||||||
userSig = result.userSig;
|
userSig = result.userSig;
|
||||||
userToken = result.accessToken;
|
userToken = result.userToken;
|
||||||
userInfo.value = result.userInfo;
|
userInfo.value = result.userInfo;
|
||||||
|
|
||||||
isLogin.value = true;
|
isLogin.value = true;
|
||||||
@@ -88,7 +94,6 @@ class AuthService extends GetxService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateUserInfo(String key, String value) async {
|
Future<void> updateUserInfo(String key, String value) async {
|
||||||
// userInfo.value.nickname = nickname;
|
|
||||||
if (key == 'nickname') {
|
if (key == 'nickname') {
|
||||||
userInfo.value.nickname = value;
|
userInfo.value.nickname = value;
|
||||||
} else if (key == 'avatar') {
|
} else if (key == 'avatar') {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import 'package:chat/configs/app_colors.dart';
|
import 'package:chat/configs/app_colors.dart';
|
||||||
|
import 'package:chat/routes/app_routes.dart';
|
||||||
|
import 'package:chat/services/auth_service.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
@@ -11,13 +13,21 @@ class AuthCreateVerifyPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _AuthCreateVerifyPageState extends State<AuthCreateVerifyPage> {
|
class _AuthCreateVerifyPageState extends State<AuthCreateVerifyPage> {
|
||||||
late final List<String> _mnemonicList;
|
late final List<String> _mnemonicList;
|
||||||
|
late final List<String> _originList;
|
||||||
|
List<String> _sureList = List<String>.generate(12, (index) => '');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
Get.arguments['language'];
|
Get.arguments['language'];
|
||||||
var m = Get.arguments['mnemonic'] as List<String>;
|
var m = Get.arguments['mnemonic'] as List<String>;
|
||||||
|
_originList = List.from(m);
|
||||||
m.shuffle();
|
m.shuffle();
|
||||||
_mnemonicList = m;
|
_mnemonicList = m;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_sureList = _originList;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -26,21 +36,57 @@ class _AuthCreateVerifyPageState extends State<AuthCreateVerifyPage> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('校验助记词'),
|
title: const Text('校验助记词'),
|
||||||
),
|
),
|
||||||
body: _moArea(_mnemonicList),
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
children: [
|
||||||
|
_sureArea(),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
|
child: Text('请按正确顺序点击您所备份的助记词'),
|
||||||
|
),
|
||||||
|
_moArea(_mnemonicList),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_sureList = List<String>.generate(12, (index) => '');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: const Text('重新输入'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _originList.join('') == _sureList.join('')
|
||||||
|
? () async {
|
||||||
|
var result =
|
||||||
|
await AuthService.to.login(_originList.join(' '));
|
||||||
|
if (result) {
|
||||||
|
Get.offAllNamed(AppRoutes.app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: const Text('确认备份'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _moArea(List<String> mnemonic) {
|
Widget _sureArea() {
|
||||||
return Padding(
|
return GridView.builder(
|
||||||
padding: const EdgeInsets.all(16.0),
|
shrinkWrap: true,
|
||||||
child: GridView.builder(
|
physics: const ClampingScrollPhysics(),
|
||||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
crossAxisCount: 2,
|
crossAxisCount: 2,
|
||||||
childAspectRatio: 4.5 / 1,
|
childAspectRatio: 4.5 / 1,
|
||||||
crossAxisSpacing: 8,
|
crossAxisSpacing: 8,
|
||||||
mainAxisSpacing: 8,
|
mainAxisSpacing: 8,
|
||||||
),
|
),
|
||||||
itemCount: mnemonic.length,
|
itemCount: 12,
|
||||||
itemBuilder: (_, i) {
|
itemBuilder: (_, i) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
@@ -52,14 +98,56 @@ class _AuthCreateVerifyPageState extends State<AuthCreateVerifyPage> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${i + 1}. ${mnemonic[i]}',
|
'${i + 1}. ${_sureList[i]}',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _moArea(List<String> mnemonic) {
|
||||||
|
return GridView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const ClampingScrollPhysics(),
|
||||||
|
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 2,
|
||||||
|
childAspectRatio: 4.5 / 1,
|
||||||
|
crossAxisSpacing: 8,
|
||||||
|
mainAxisSpacing: 8,
|
||||||
),
|
),
|
||||||
|
itemCount: mnemonic.length,
|
||||||
|
itemBuilder: (_, i) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: !_sureList.contains(mnemonic[i])
|
||||||
|
? () {
|
||||||
|
int len = _sureList.where((element) => element != '').length;
|
||||||
|
setState(() {
|
||||||
|
_sureList[len] = mnemonic[i];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: _sureList.contains(mnemonic[i]) ? AppColors.primary : null,
|
||||||
|
border: Border.all(
|
||||||
|
color: AppColors.border,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
mnemonic[i],
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:chat/configs/app_colors.dart';
|
import 'package:chat/configs/app_colors.dart';
|
||||||
import 'package:chat/routes/app_routes.dart';
|
import 'package:chat/routes/app_routes.dart';
|
||||||
import 'package:chat/services/auth_service.dart';
|
import 'package:chat/services/auth_service.dart';
|
||||||
import 'package:chat/utils/hd_wallet.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
@@ -13,24 +12,7 @@ class AuthImportPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _AuthImportPageState extends State<AuthImportPage> {
|
class _AuthImportPageState extends State<AuthImportPage> {
|
||||||
final TextEditingController _editingController = TextEditingController();
|
String _mn = '';
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_editingController.text =
|
|
||||||
'demise sell awesome tragic faith village party elbow lady leopard wrestle civil';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_editingController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -42,7 +24,6 @@ class _AuthImportPageState extends State<AuthImportPage> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
controller: _editingController,
|
|
||||||
maxLines: 5,
|
maxLines: 5,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
hintText: '请输入您的助记词,以空格分割单词或汉字',
|
hintText: '请输入您的助记词,以空格分割单词或汉字',
|
||||||
@@ -53,21 +34,24 @@ class _AuthImportPageState extends State<AuthImportPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
onChanged: (e) {
|
||||||
|
setState(() {
|
||||||
|
_mn = e;
|
||||||
|
});
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
const Text('支持导入所有遵循BIP标准生成的助记词'),
|
const Text('支持导入所有遵循BIP标准生成的助记词'),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () async {
|
onPressed: _mn.isNotEmpty
|
||||||
String? address =
|
? () async {
|
||||||
HDWallet.mnemonicToAddress(_editingController.text);
|
var result = await AuthService.to.login(_mn);
|
||||||
if (address != null) {
|
|
||||||
var result = await AuthService.to.login(address);
|
|
||||||
if (result) {
|
if (result) {
|
||||||
Get.offAllNamed(AppRoutes.app);
|
Get.offAllNamed(AppRoutes.app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
: null,
|
||||||
child: const Text('开始导入'),
|
child: const Text('开始导入'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:chat/configs/app_colors.dart';
|
||||||
import 'package:chat/routes/auth_routes.dart';
|
import 'package:chat/routes/auth_routes.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -13,20 +14,69 @@ class _AuthPageState extends State<AuthPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
body: Padding(
|
||||||
title: const Text('ZH-CHAT'),
|
padding: const EdgeInsets.all(24.0),
|
||||||
),
|
child: Column(
|
||||||
body: Column(
|
|
||||||
children: [
|
children: [
|
||||||
|
const SizedBox(height: 128),
|
||||||
|
const Text(
|
||||||
|
'ZH-CHAT',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 48,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: AppColors.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
Image.asset(
|
||||||
|
'assets/images/login_bg.png',
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
color: AppColors.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 48),
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppColors.active,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
image: const DecorationImage(
|
||||||
|
image: AssetImage('assets/images/login_bg.png'),
|
||||||
|
opacity: 0.2,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
alignment: Alignment.topRight,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'助记词账户',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.white,
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 40),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
children: [
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.toNamed(AuthRoutes.create);
|
Get.toNamed(AuthRoutes.create);
|
||||||
},
|
},
|
||||||
child: const Text('创建账户'),
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.all(
|
||||||
|
AppColors.white,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'创建账户',
|
||||||
|
style: TextStyle(
|
||||||
|
color: AppColors.active,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Get.toNamed(AuthRoutes.import);
|
Get.toNamed(AuthRoutes.import);
|
||||||
@@ -37,6 +87,10 @@ class _AuthPageState extends State<AuthPage> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user