fix: 登录按钮对认不出的输入给出提示,不再静默无反应
- SGWCMAID 前缀改成按粘贴原文判断:令牌取的是内容的后 64 位,粘贴内容一旦超过 64 位,前缀就被截掉了,原先对截取结果做 startsWith 会直接 return, 点按钮看着能点却一声不响 - 补 test/login_page_test.dart 覆盖两条输入路径:不认识的令牌给提示, 连接信息把按钮切成「恢复会话」
This commit is contained in:
1 parent
5d16984e4e
commit
e74bb792bd
3 files changed
+50
-2
No files matched your search
@@ -21,6 +21,7 @@ class AppStrings {
|
|||||||
static const qrScanError = '解析失败';
|
static const qrScanError = '解析失败';
|
||||||
static const forcePreviewApi = '强制使用 Preview API';
|
static const forcePreviewApi = '强制使用 Preview API';
|
||||||
static const loginFailed = '登录失败';
|
static const loginFailed = '登录失败';
|
||||||
|
static const qrTokenUnrecognized = '没认出 QR 令牌(内容里应当含 SGWCMAID),也可以粘贴「连接信息」。';
|
||||||
static const requestFailed = '请求失败';
|
static const requestFailed = '请求失败';
|
||||||
static const settingsTooltip = '设置';
|
static const settingsTooltip = '设置';
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class LoginPage extends StatefulWidget {
|
|||||||
class _LoginPageState extends State<LoginPage> {
|
class _LoginPageState extends State<LoginPage> {
|
||||||
final _qrController = TextEditingController();
|
final _qrController = TextEditingController();
|
||||||
String _qrCode = '';
|
String _qrCode = '';
|
||||||
|
String _rawInput = '';
|
||||||
SessionShare? _share;
|
SessionShare? _share;
|
||||||
bool _loading = false;
|
bool _loading = false;
|
||||||
bool _forcePreviewApi = false;
|
bool _forcePreviewApi = false;
|
||||||
@@ -36,6 +37,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
void _onQRContentChanged(String value) {
|
void _onQRContentChanged(String value) {
|
||||||
final text = value.trim();
|
final text = value.trim();
|
||||||
setState(() {
|
setState(() {
|
||||||
|
_rawInput = text;
|
||||||
_qrCode = SessionModel.extractQRCode(text);
|
_qrCode = SessionModel.extractQRCode(text);
|
||||||
_share = SessionShare.tryDecode(text);
|
_share = SessionShare.tryDecode(text);
|
||||||
});
|
});
|
||||||
@@ -51,6 +53,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
if (result != null && result.isNotEmpty) {
|
if (result != null && result.isNotEmpty) {
|
||||||
_qrController.text = result;
|
_qrController.text = result;
|
||||||
setState(() {
|
setState(() {
|
||||||
|
_rawInput = result.trim();
|
||||||
_qrCode = SessionModel.extractQRCode(result);
|
_qrCode = SessionModel.extractQRCode(result);
|
||||||
_share = SessionShare.tryDecode(result);
|
_share = SessionShare.tryDecode(result);
|
||||||
});
|
});
|
||||||
@@ -78,7 +81,12 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
Future<void> _onLogin() async {
|
Future<void> _onLogin() async {
|
||||||
if (_qrCode.isEmpty) return;
|
if (_qrCode.isEmpty) return;
|
||||||
|
|
||||||
if (_qrCode.startsWith("SGWCMAID")) {
|
// 令牌是粘贴内容的后 64 位,前缀可能在截取之后就没了,所以要拿原文判断;
|
||||||
|
// 认不出来时必须给提示,否则点了按钮一声不响,像是坏了。
|
||||||
|
if (!_rawInput.contains('SGWCMAID')) {
|
||||||
|
context.showSnack(AppStrings.qrTokenUnrecognized);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setState(() => _loading = true);
|
setState(() => _loading = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -117,7 +125,6 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// 实验性:用主页导出的连接信息恢复会话。带可用 JSESSIONID 就直接续上那次登录,
|
/// 实验性:用主页导出的连接信息恢复会话。带可用 JSESSIONID 就直接续上那次登录,
|
||||||
/// 否则退回用令牌重新登录。
|
/// 否则退回用令牌重新登录。
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:ichino/config/strings.dart';
|
||||||
|
import 'package:ichino/main.dart';
|
||||||
|
import 'package:ichino/models/session_share.dart';
|
||||||
|
|
||||||
|
/// 登录页的输入既可能是 QR 令牌,也可能是主页导出的「连接信息」,
|
||||||
|
/// 两条路都要有可见反馈,不能出现点了没反应。
|
||||||
|
void main() {
|
||||||
|
testWidgets('粘贴不认识的令牌时点登录会给出提示', (tester) async {
|
||||||
|
await tester.pumpWidget(const MyApp());
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
// 72 位:截取的后 64 位里没有 SGWCMAID 前缀
|
||||||
|
await tester.enterText(find.byType(TextField), 'ABCDEF' * 12);
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
await tester.tap(find.text(AppStrings.login));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(find.text(AppStrings.qrTokenUnrecognized), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('粘贴连接信息时按钮切成「恢复会话」', (tester) async {
|
||||||
|
await tester.pumpWidget(const MyApp());
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
const share = SessionShare(
|
||||||
|
userId: 7,
|
||||||
|
token: 'SGWCMAIDtoken',
|
||||||
|
cookie: 'JSESSIONID=x',
|
||||||
|
);
|
||||||
|
await tester.enterText(find.byType(TextField), share.encode());
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(find.text(AppStrings.sessionShareDetected), findsOneWidget);
|
||||||
|
expect(find.text(AppStrings.restoreSession), findsOneWidget);
|
||||||
|
expect(find.text(AppStrings.login), findsNothing);
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in new issue
Block a user