fix: follow undergraduate login links and capture live history URLs

This commit is contained in:
Codex
2026-10-15 17:17:54 +08:00
parent 79d268fd5e
commit defe7fd50e
14 changed files with 213 additions and 32 deletions
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:webview_flutter/webview_flutter.dart';
@@ -318,13 +319,35 @@ class UndergraduateSession extends ChangeNotifier {
});
}
Future<UndergraduatePageEvidence> _evidence(Uri uri, bool capture) async =>
UndergraduatePageEvidence.decode(
await web.runJavaScriptReturningResult(
capture ? undergraduateCaptureScript : undergraduateStatusProbeScript,
),
uri,
Future<UndergraduatePageEvidence> _evidence(Uri uri, bool capture) async {
// loadDataWithBaseURL can leave native getUrl at the original address after
// the school's History API changes location. Bind capture to the live URL,
// still requiring the native and live documents to share the school origin.
dynamic location = await web.runJavaScriptReturningResult('location.href');
if (location is String && location.startsWith('"')) {
location = jsonDecode(location);
}
final live = location is String ? Uri.tryParse(location) : null;
if (live == null ||
!UndergraduateNavigationPolicy.isDataPage(uri) ||
!UndergraduateNavigationPolicy.isDataPage(live) ||
uri.origin != live.origin) {
throw const FormatException('页面来源无效,请重新打开学校课表。');
}
if (live != uri) {
DiagnosticLog.instance.add(
'school_document_url',
fields: {'school': 'undergraduate', 'code': 'history_state'},
);
}
return UndergraduatePageEvidence.decode(
await web.runJavaScriptReturningResult(
capture ? undergraduateCaptureScript : undergraduateStatusProbeScript,
),
live,
);
}
Future<void> _loaded(String url) async {
DiagnosticLog.instance.navigation('undergraduate', 'finished', url);
final g = _generation, d = _document, key = '$_generation:$_document';
@@ -361,18 +384,20 @@ class UndergraduateSession extends ChangeNotifier {
}
_connected = true;
awaitingAuthentication = false;
final recovery = await _pageRecovery.tryRestore(
web,
uri,
authenticated: true,
documentKey: '$g:$d',
isCurrent: () => _valid(g) && d == _document,
onStarted: () {
_recoveringPage = true;
message = '已登录,正在恢复完整教务页面…';
_emit();
},
);
final recovery = uri != status.url
? FullPageRecoveryResult.unchanged
: await _pageRecovery.tryRestore(
web,
uri,
authenticated: true,
documentKey: '$g:$d',
isCurrent: () => _valid(g) && d == _document,
onStarted: () {
_recoveringPage = true;
message = '已登录,正在恢复完整教务页面…';
_emit();
},
);
if (!_valid(g) || d != _document) return;
_recoveringPage = false;
if (recovery == FullPageRecoveryResult.restored) {
@@ -397,7 +422,7 @@ class UndergraduateSession extends ChangeNotifier {
_emit();
return;
}
if (_expected == null || uri.toString() != _expected.toString()) {
if (_expected == null || status.url.toString() != _expected.toString()) {
await _requestExam(g);
return;
}