113 lines
3.4 KiB
Dart
113 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../../core/app_state.dart';
|
|
import '../../core/app_theme.dart';
|
|
import '../../core/sherpa_stt_service.dart';
|
|
import '../../widgets/app_widgets.dart';
|
|
import 'profile_widgets.dart';
|
|
|
|
/// 学习偏好:每日时长、中文提示与语音识别。
|
|
class LearningPreferencesView extends StatelessWidget {
|
|
const LearningPreferencesView({super.key, required this.state});
|
|
final AppState state;
|
|
|
|
@override
|
|
Widget build(BuildContext context) => SpacedColumn(
|
|
spacing: 16,
|
|
children: [
|
|
MenuGroup(
|
|
children: [
|
|
MenuTile(
|
|
icon: Icons.timer_outlined,
|
|
title: '每日学习时间',
|
|
value: '${state.dailyMinutes} 分钟',
|
|
onTap: () => _chooseDuration(context),
|
|
),
|
|
MenuSwitch(
|
|
icon: Icons.translate,
|
|
title: '默认显示中文提示',
|
|
subtitle: 'A0 阶段建议开启',
|
|
value: state.showChineseHints,
|
|
onChanged: state.toggleChineseHints,
|
|
),
|
|
],
|
|
),
|
|
MenuGroup(
|
|
title: '语音',
|
|
children: [
|
|
MenuTile(
|
|
icon: Icons.graphic_eq,
|
|
title: '离线语音识别',
|
|
subtitle: SherpaSttService.instance.isReady
|
|
? 'SenseVoice-Small · 已就绪,本地识别'
|
|
: 'SenseVoice-Small · 已内置,无需下载',
|
|
trailing: Icon(
|
|
Icons.check_circle,
|
|
color: AppColors.green,
|
|
size: 20,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
|
|
Future<void> _chooseDuration(BuildContext context) async {
|
|
final value = await showModalBottomSheet<int>(
|
|
context: context,
|
|
builder: (context) => SafeArea(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
for (final minute in [10, 20, 30])
|
|
ListTile(
|
|
title: Text('$minute 分钟'),
|
|
trailing: state.dailyMinutes == minute
|
|
? const Icon(Icons.check)
|
|
: null,
|
|
onTap: () => Navigator.pop(context, minute),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
if (value != null) state.setDailyMinutes(value);
|
|
}
|
|
}
|
|
|
|
/// 外观:浅色 / 深色 / 跟随系统。
|
|
class AppearanceView extends StatelessWidget {
|
|
const AppearanceView({super.key, required this.state});
|
|
final AppState state;
|
|
|
|
@override
|
|
Widget build(BuildContext context) => SpacedColumn(
|
|
children: [
|
|
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: {state.themeMode},
|
|
showSelectedIcon: false,
|
|
onSelectionChanged: (selection) =>
|
|
state.setThemeMode(selection.first),
|
|
),
|
|
),
|
|
Text(
|
|
'深色模式适合夜间使用;跟随系统会随手机的深色开关自动切换。',
|
|
style: TextStyle(fontSize: 12, color: AppColors.muted),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
String themeModeLabel(AppThemeMode mode) => switch (mode) {
|
|
AppThemeMode.system => '跟随系统',
|
|
AppThemeMode.light => '浅色',
|
|
AppThemeMode.dark => '深色',
|
|
};
|