feat: A1 短材料复现本单元理解词,并加入黑夜模式

课程内容
- 重写全部 21 个 A1 单元的听读材料,把本单元理解词织进听/读文本,
  单元内理解词复现率从约 20% 提升到约 77%(各单元 56–96%)。
- 修正 U01 房间号与机场大巴同为 thirty 的撞车(改为 17/30/40)。
- 校验器容差按级别读取(A1 为 8%),materials 覆盖率、字数、
  选项子串等校验全部通过;course_content_test 通过。

黑夜模式
- app_theme 拆分明/暗两套调色板,AppColors 随亮度切换;
  main 用 theme/darkTheme/themeMode + builder 镜像已解析亮度;
  主题偏好持久化到快照;进度页新增“外观主题”切换。

文档
- COURSE-PACK-JSON.md 更新 A1 词池覆盖(840/933)与材料复现约定。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-18 11:16:09 +09:00
co-authored by Claude Opus 4.8
parent 9ab08c25ef
commit febfd30f49
93 changed files with 72676 additions and 274 deletions
@@ -130,14 +130,14 @@ class ProgressPage extends StatelessWidget {
],
),
),
const Icon(Icons.chevron_right, color: AppColors.muted),
Icon(Icons.chevron_right, color: AppColors.muted),
],
),
);
},
),
if (state.a0Passed)
const SectionCard(
SectionCard(
tint: AppColors.softGreen,
child: Text('A0 已通过。A1 主线内容尚未提供,可继续进行 A0 巩固。'),
),
@@ -311,6 +311,41 @@ class _SettingsPageState extends State<SettingsPage> {
activeThumbColor: AppColors.green,
onChanged: widget.state.toggleKeepRecordings,
),
Padding(
padding: const EdgeInsets.fromLTRB(4, 10, 4, 6),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'外观主题',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
const SizedBox(height: 4),
Text(
'深色模式适合夜间使用;跟随系统会随手机的深色开关自动切换',
style: TextStyle(fontSize: 12, color: AppColors.muted),
),
const SizedBox(height: 10),
SizedBox(
width: double.infinity,
child: SegmentedButton<AppThemeMode>(
segments: const [
ButtonSegment(
value: AppThemeMode.system,
label: Text('跟随系统'),
),
ButtonSegment(value: AppThemeMode.light, label: Text('浅色')),
ButtonSegment(value: AppThemeMode.dark, label: Text('深色')),
],
selected: {widget.state.themeMode},
showSelectedIcon: false,
onSelectionChanged: (selection) =>
widget.state.setThemeMode(selection.first),
),
),
],
),
),
_SettingTile(
title: '已保存的录音',
subtitle: '回听或删除本机英语练习录音',
@@ -326,7 +361,7 @@ class _SettingsPageState extends State<SettingsPage> {
'离线语音识别引擎',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
const Text(
Text(
'已内置 SenseVoice-Small 高精度离线语音识别模型 (INT8)。随 App 安装包直接打包,离线即用,无需额外下载,零网络流量消耗。',
style: TextStyle(fontSize: 12, color: AppColors.muted),
),
@@ -335,14 +370,14 @@ class _SettingsPageState extends State<SettingsPage> {
subtitle: SherpaSttService.instance.isReady
? '已就绪 · 本地离线识别 (16kHz WAV · INT8)'
: '预加载就绪 · 已内置打包',
trailing: const Icon(Icons.check_circle, color: AppColors.green, size: 20),
trailing: Icon(Icons.check_circle, color: AppColors.green, size: 20),
),
const Divider(height: 28),
const Text(
'云同步与多端备份',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
const Text(
Text(
'支持通过自建服务器在 Android / iOS / macOS 之间同步学习进度与复习掌握度。离线自动缓存,联网自动双向合并。',
style: TextStyle(fontSize: 12, color: AppColors.muted),
),
@@ -363,7 +398,7 @@ class _SettingsPageState extends State<SettingsPage> {
'AI 对话服务',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
const Text(
Text(
'订阅版 ChatGPT / Gemini 不能直接作为 App API 使用。请使用自己的 API Key,或填写兼容 OpenAI 接口的 CLIProxyAPI 地址。密钥不在此页面保存。',
style: TextStyle(fontSize: 12, color: AppColors.muted),
),
@@ -568,7 +603,7 @@ class _SettingsPageState extends State<SettingsPage> {
SectionCard(
child: Row(
children: [
const Icon(Icons.mic_none, color: AppColors.green),
Icon(Icons.mic_none, color: AppColors.green),
const SizedBox(width: 10),
Expanded(
child: Text(