init
This commit is contained in:
161
lib/app/features/settings/pages/settings_page.dart
Normal file
161
lib/app/features/settings/pages/settings_page.dart
Normal file
@@ -0,0 +1,161 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../theme/theme_mode_controller.dart';
|
||||
import '../controller/settings_controller.dart';
|
||||
|
||||
class SettingsPage extends ConsumerWidget {
|
||||
const SettingsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final settingsAsync = ref.watch(settingsControllerProvider);
|
||||
final themeMode = ref.watch(themeModeControllerProvider);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Settings')),
|
||||
body: settingsAsync.when(
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, _) => Center(child: Text(error.toString())),
|
||||
data: (settings) {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.brightness_6_rounded),
|
||||
title: const Text('主题模式'),
|
||||
subtitle: Text(themeMode.name),
|
||||
trailing: SegmentedButton<ThemeMode>(
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: ThemeMode.light,
|
||||
icon: Icon(Icons.light_mode_rounded),
|
||||
label: Text('Light'),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: ThemeMode.dark,
|
||||
icon: Icon(Icons.dark_mode_rounded),
|
||||
label: Text('Dark'),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: ThemeMode.system,
|
||||
icon: Icon(Icons.settings_suggest_rounded),
|
||||
label: Text('System'),
|
||||
),
|
||||
],
|
||||
selected: {themeMode},
|
||||
onSelectionChanged: (selection) => ref
|
||||
.read(themeModeControllerProvider.notifier)
|
||||
.setThemeMode(selection.first),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.badge_rounded),
|
||||
title: const Text('Hostname'),
|
||||
subtitle: Text(settings.hostname),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.edit_rounded),
|
||||
onPressed: () => _editText(
|
||||
context: context,
|
||||
title: 'Hostname',
|
||||
initial: settings.hostname,
|
||||
onSubmit: (value) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateHostname(value),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.folder_rounded),
|
||||
title: const Text('默认保存路径'),
|
||||
subtitle: Text(settings.savePath),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.edit_rounded),
|
||||
onPressed: () => _editText(
|
||||
context: context,
|
||||
title: '保存路径',
|
||||
initial: settings.savePath,
|
||||
onSubmit: (value) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateSavePath(value),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
SwitchListTile.adaptive(
|
||||
secondary: const Icon(Icons.auto_mode_rounded),
|
||||
title: const Text('自动接收'),
|
||||
value: settings.autoAccept,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateAutoAccept(v),
|
||||
),
|
||||
SwitchListTile.adaptive(
|
||||
secondary: const Icon(Icons.history_rounded),
|
||||
title: const Text('保存历史记录'),
|
||||
value: settings.saveHistory,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateSaveHistory(v),
|
||||
),
|
||||
SwitchListTile.adaptive(
|
||||
secondary: const Icon(Icons.shield_rounded),
|
||||
title: const Text('启用 TLS'),
|
||||
value: settings.enableTls,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateEnableTls(v),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _editText({
|
||||
required BuildContext context,
|
||||
required String title,
|
||||
required String initial,
|
||||
required Future<void> Function(String value) onSubmit,
|
||||
}) async {
|
||||
final controller = TextEditingController(text: initial);
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
return AlertDialog(
|
||||
title: Text(title),
|
||||
content: TextField(controller: controller),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
child: const Text('保存'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (confirmed == true) {
|
||||
await onSubmit(controller.text.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user