feat: select school terms and smooth refractive Dock motion
This commit is contained in:
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
import '../../app/app_controller.dart';
|
||||
import '../../domain/school_term.dart';
|
||||
import 'school_session.dart';
|
||||
|
||||
class SchoolAuthPage extends StatefulWidget {
|
||||
@@ -18,6 +19,7 @@ class SchoolAuthPage extends StatefulWidget {
|
||||
|
||||
class _SchoolAuthPageState extends State<SchoolAuthPage> {
|
||||
bool _saving = false;
|
||||
SchoolTerm? _termChoice;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -36,7 +38,9 @@ class _SchoolAuthPageState extends State<SchoolAuthPage> {
|
||||
final courses = s.pendingDraft, exams = s.pendingExams;
|
||||
final generation = s.pageGeneration;
|
||||
final route = ModalRoute.of(context);
|
||||
if (_saving || (courses == null && exams == null)) return;
|
||||
if (s.needsTermSelection || _saving || (courses == null && exams == null)) {
|
||||
return;
|
||||
}
|
||||
_saving = true;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
if (!mounted) {
|
||||
@@ -102,7 +106,9 @@ class _SchoolAuthPageState extends State<SchoolAuthPage> {
|
||||
),
|
||||
IconButton(
|
||||
tooltip: '读取当前页面',
|
||||
onPressed: _saving ? null : s.readCurrentPage,
|
||||
onPressed: _saving || s.needsTermSelection
|
||||
? null
|
||||
: s.readCurrentPage,
|
||||
icon: const Icon(Icons.sync_rounded),
|
||||
),
|
||||
],
|
||||
@@ -123,7 +129,9 @@ class _SchoolAuthPageState extends State<SchoolAuthPage> {
|
||||
child: Stack(
|
||||
children: [
|
||||
WebViewWidget(controller: s.web),
|
||||
if (s.finding || _saving)
|
||||
if (s.needsTermSelection)
|
||||
Positioned.fill(child: _termPicker(s)),
|
||||
if (!s.needsTermSelection && (s.finding || _saving))
|
||||
Positioned.fill(
|
||||
child: ColoredBox(
|
||||
color: const Color(0xFFF5F9FE),
|
||||
@@ -152,4 +160,62 @@ class _SchoolAuthPageState extends State<SchoolAuthPage> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _termPicker(SchoolSession session) {
|
||||
final choices = session.termChoices;
|
||||
final preferred =
|
||||
_termChoice ??
|
||||
session.selectedTerm ??
|
||||
widget.controller.snapshot.schoolTerm ??
|
||||
choices.first;
|
||||
final selected = choices.contains(preferred) ? preferred : choices.first;
|
||||
return Material(
|
||||
color: const Color(0xFFF5F9FE),
|
||||
child: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 16, 20, 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Text(
|
||||
'选择学校学期',
|
||||
style: TextStyle(fontSize: 22, fontWeight: FontWeight.w700),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(session.requestingExams ? '将读取这个学期的考试安排。' : '将读取这个学期的课程表。'),
|
||||
const SizedBox(height: 12),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: choices.length,
|
||||
itemBuilder: (context, index) {
|
||||
final term = choices[index];
|
||||
final isSelected = term == selected;
|
||||
return ListTile(
|
||||
title: Text(term.label),
|
||||
selected: isSelected,
|
||||
leading: Icon(
|
||||
isSelected
|
||||
? Icons.radio_button_checked
|
||||
: Icons.radio_button_off,
|
||||
),
|
||||
onTap: () => setState(() => _termChoice = term),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
FilledButton(
|
||||
onPressed: () => session.selectTerm(selected),
|
||||
child: const Text('导入所选学期'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user