Files
TPSchedule/mobile/lib/features/school/school_auth_page.dart
T

153 lines
4.5 KiB
Dart

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<SchoolAuthPage> createState() => _SchoolAuthPageState();
}
class _SchoolAuthPageState extends State<SchoolAuthPage> {
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
? '正在查找考试安排,请稍候'
: '正在查找课表,请稍候'),
),
],
),
),
),
),
],
),
),
],
),
);
}
}