import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../app/app_controller.dart'; import 'school_session.dart'; class SchoolAuthPage extends StatefulWidget { const SchoolAuthPage({ super.key, required this.session, required this.controller, }); final SchoolSession session; final AppController controller; @override State createState() => _SchoolAuthPageState(); } class _SchoolAuthPageState extends State { bool _saving = false; @override void initState() { super.initState(); widget.session.addListener(_changed); WidgetsBinding.instance.addPostFrameCallback((_) => _changed()); } void _changed() { if (!mounted) return; setState(() {}); final s = widget.session; final courses = s.pendingDraft, exams = s.pendingExams; final generation = s.pageGeneration; final route = ModalRoute.of(context); if (_saving || (courses == null && exams == null)) return; _saving = true; WidgetsBinding.instance.addPostFrameCallback((_) async { if (!mounted) { _saving = false; return; } // The session draft must still belong to the same page after navigation. if (generation != s.pageGeneration || courses != s.pendingDraft || exams != s.pendingExams) { _saving = false; _changed(); return; } if (courses != null) { await widget.controller.applyImport(courses, confirmedEmpty: false); } if (exams != null) await widget.controller.applyExams(exams); final success = widget.controller.lastError == null; final acknowledged = s.saved( success: success, generation: generation, draft: courses, exams: exams, ); _saving = false; if (!mounted) return; if (!acknowledged) { _changed(); return; } if (success && route?.isCurrent == true) { Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(exams == null ? '课表已导入;请核对学期开始日。' : '考试信息已更新'), ), ); } else { setState(() {}); } }); } @override void dispose() { widget.session.removeListener(_changed); super.dispose(); } @override Widget build(BuildContext context) { final s = widget.session; return Scaffold( appBar: AppBar( title: const Text('学校认证'), actions: [ IconButton( tooltip: '重新认证', onPressed: _saving ? null : s.openAuthentication, icon: const Icon(Icons.refresh_rounded), ), IconButton( tooltip: '重试读取', onPressed: _saving ? null : (s.requestingExams ? s.openExams : s.openTimetable), icon: const Icon(Icons.sync_rounded), ), ], ), body: Column( children: [ if (s.busy || _saving) const LinearProgressIndicator(minHeight: 2), Container( width: double.infinity, padding: const EdgeInsets.all(12), color: const Color(0xFFEFF6FF), child: Text( s.message, style: const TextStyle(fontSize: 12, height: 1.5), ), ), Expanded( child: Stack( children: [ WebViewWidget(controller: s.web), if (s.finding || _saving) Positioned.fill( child: ColoredBox( color: const Color(0xFFF5F9FE), child: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const CircularProgressIndicator(), const SizedBox(height: 20), Text( _saving ? '正在保存,请稍候' : (s.requestingExams ? '正在查找考试安排,请稍候' : '正在查找课表,请稍候'), ), ], ), ), ), ), ], ), ), ], ), ); } }