feat:improve logic

This commit is contained in:
Cookiues committed 2026-05-29 12:51:23 +08:00
1 parent a78a87e46b
commit dca69d095a
4 files changed
+105 -8

No files matched your search

+1
View File
@@ -19,6 +19,7 @@ class AppStrings {
static const qrScanSuccess = '二维码解析成功'; static const qrScanSuccess = '二维码解析成功';
static const qrScanFailed = '未能识别二维码,请手动粘贴内容'; static const qrScanFailed = '未能识别二维码,请手动粘贴内容';
static const qrScanError = '解析失败'; static const qrScanError = '解析失败';
static const forcePreviewApi = '强制使用 Preview API';
static const loginFailed = '登录失败'; static const loginFailed = '登录失败';
static const requestFailed = '请求失败'; static const requestFailed = '请求失败';
static const settingsTooltip = '设置'; static const settingsTooltip = '设置';
+11
View File
@@ -51,6 +51,7 @@ class _LoginPageState extends State<LoginPage> {
final _apiService = ApiService(); final _apiService = ApiService();
String _qrCode = ''; String _qrCode = '';
bool _loading = false; bool _loading = false;
bool _forcePreviewApi = false;
@override @override
void dispose() { void dispose() {
@@ -115,6 +116,7 @@ class _LoginPageState extends State<LoginPage> {
userId: result.userId, userId: result.userId,
token: result.token, token: result.token,
cookies: result.cookies, cookies: result.cookies,
forcePreviewApi: _forcePreviewApi,
), ),
), ),
); );
@@ -317,6 +319,15 @@ class _LoginPageState extends State<LoginPage> {
), ),
], ],
), ),
const SizedBox(height: 16),
CheckboxListTile(
value: _forcePreviewApi,
onChanged: (v) => setState(() => _forcePreviewApi = v ?? false),
title: const Text(AppStrings.forcePreviewApi),
controlAffinity: ListTileControlAffinity.leading,
contentPadding: EdgeInsets.zero,
dense: true,
),
], ],
), ),
), ),
+90 -7
View File
@@ -14,12 +14,14 @@ class HomePage extends StatefulWidget {
final int userId; final int userId;
final String token; final String token;
final String? cookies; final String? cookies;
final bool forcePreviewApi;
const HomePage({ const HomePage({
super.key, super.key,
required this.userId, required this.userId,
required this.token, required this.token,
this.cookies, this.cookies,
this.forcePreviewApi = false,
}); });
@override @override
@@ -34,6 +36,7 @@ class _HomePageState extends State<HomePage> {
String? _error; String? _error;
bool _loading = true; bool _loading = true;
bool _loggingOut = false; bool _loggingOut = false;
String? _sessionCookies;
static const _tabTitles = [ static const _tabTitles = [
AppStrings.tabHome, AppStrings.tabHome,
@@ -76,10 +79,12 @@ class _HomePageState extends State<HomePage> {
token: widget.token, token: widget.token,
); );
if (!mounted) return; if (!mounted) return;
_sessionCookies = service.cookies;
setState(() => _preview = preview); setState(() => _preview = preview);
// isLogin == true => 已有人登录, 不再走完整登录, 直接展示 preview 概要 // isLogin == true => 已有人登录, 不再走完整登录, 直接展示 preview 概要
if (preview.isLogin) { // forcePreviewApi => 跳过 UserLoginApi, 仅展示 preview + Login 按钮
if (preview.isLogin || widget.forcePreviewApi) {
setState(() => _loading = false); setState(() => _loading = false);
return; return;
} }
@@ -89,10 +94,55 @@ class _HomePageState extends State<HomePage> {
token: widget.token, token: widget.token,
); );
if (!mounted) return; if (!mounted) return;
_sessionCookies = service.cookies;
setState(() => _login = login); setState(() => _login = login);
final userData = await service.getUserDataTyped(widget.userId); final userData = await service.getUserDataTyped(widget.userId);
if (!mounted) return; if (!mounted) return;
_sessionCookies = service.cookies;
setState(() {
_userData = userData;
_loading = false;
});
} on TitleApiException catch (e) {
if (!mounted) return;
setState(() {
_error = e.message;
_loading = false;
});
} catch (e) {
if (!mounted) return;
setState(() {
_error = e.toString();
_loading = false;
});
}
}
Future<void> _performLogin() async {
if (!TitleServerConfigHolder().isConfigured) return;
setState(() {
_loading = true;
_error = null;
});
final service = TitleApiService(
TitleServerConfigHolder().config!,
cookies: _sessionCookies ?? widget.cookies,
);
try {
final login = await service.userLoginFull(
userId: widget.userId,
token: widget.token,
);
if (!mounted) return;
_sessionCookies = service.cookies;
setState(() => _login = login);
final userData = await service.getUserDataTyped(widget.userId);
if (!mounted) return;
_sessionCookies = service.cookies;
setState(() { setState(() {
_userData = userData; _userData = userData;
_loading = false; _loading = false;
@@ -118,7 +168,7 @@ class _HomePageState extends State<HomePage> {
if (!TitleServerConfigHolder().isConfigured) return; if (!TitleServerConfigHolder().isConfigured) return;
final service = TitleApiService( final service = TitleApiService(
TitleServerConfigHolder().config!, TitleServerConfigHolder().config!,
cookies: widget.cookies, cookies: _sessionCookies ?? widget.cookies,
); );
try { try {
await service.userLogout( await service.userLogout(
@@ -171,7 +221,7 @@ class _HomePageState extends State<HomePage> {
_buildBody(theme), _buildBody(theme),
TicketPage( TicketPage(
userId: widget.userId, userId: widget.userId,
cookies: widget.cookies, cookies: _sessionCookies ?? widget.cookies,
loginDateTime: _login?.loginDateTime, loginDateTime: _login?.loginDateTime,
playerRating: _userData?.playerRating ?? _preview?.playerRating ?? 0, playerRating: _userData?.playerRating ?? _preview?.playerRating ?? 0,
onLogoutRequested: _login != null ? _logoutSession : null, onLogoutRequested: _login != null ? _logoutSession : null,
@@ -268,8 +318,13 @@ class _HomePageState extends State<HomePage> {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
if (preview.isLogin && userData == null) { if ((preview.isLogin || (widget.forcePreviewApi && _login == null)) && userData == null) {
return _buildPreviewOnly(theme, preview); return _buildPreviewOnly(
theme,
preview,
showLoginButton: widget.forcePreviewApi && _login == null,
onLoginPressed: _performLogin,
);
} }
if (userData != null) { if (userData != null) {
@@ -279,7 +334,12 @@ class _HomePageState extends State<HomePage> {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
Widget _buildPreviewOnly(ThemeData theme, UserPreviewDataBean preview) { Widget _buildPreviewOnly(
ThemeData theme,
UserPreviewDataBean preview, {
bool showLoginButton = false,
VoidCallback? onLoginPressed,
}) {
return SingleChildScrollView( return SingleChildScrollView(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
child: ConstrainedBox( child: ConstrainedBox(
@@ -295,12 +355,35 @@ class _HomePageState extends State<HomePage> {
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: Text( child: Text(
AppStrings.inheritedAccountNotice, showLoginButton ? 'Preview API 模式,点击下方按钮登录。' : AppStrings.inheritedAccountNotice,
style: theme.textTheme.bodySmall?.copyWith( style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onTertiaryContainer, color: theme.colorScheme.onTertiaryContainer,
), ),
), ),
), ),
if (showLoginButton) ...[
const SizedBox(height: 12),
SizedBox(
width: double.infinity,
child: FilledButton.icon(
onPressed: _loading ? null : onLoginPressed,
icon: _loading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.login, size: 20),
label: Text(_loading ? AppStrings.loggingIn : AppStrings.login),
style: FilledButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
),
),
],
const SizedBox(height: 12), const SizedBox(height: 12),
_ProfileFromPreviewCard(theme: theme, preview: preview), _ProfileFromPreviewCard(theme: theme, preview: preview),
const SizedBox(height: 12), const SizedBox(height: 12),
+3 -1
View File
@@ -40,7 +40,9 @@ class TitleApiService {
final TitleServerConfig _config; final TitleServerConfig _config;
String? _cookies; String? _cookies;
TitleApiService(this._config, {this._cookies}); TitleApiService(this._config, {String? cookies}) : _cookies = cookies;
String? get cookies => _cookies;
Uint8List _aesEncrypt(Uint8List plaintext) { Uint8List _aesEncrypt(Uint8List plaintext) {
final cipher = PaddedBlockCipherImpl( final cipher = PaddedBlockCipherImpl(