Add settings screen for server URL and API token configuration

- New SettingsScreen with server_url and api_token fields, saved to SharedPreferences
- Add settings gear icon to HomeScreen AppBar
- Allows users to configure backend connection before first upload

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-05-27 20:08:35 +08:00
parent d11f33380c
commit d435de3bd0
2 changed files with 102 additions and 1 deletions

View File

@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import '../widgets/record_bottom_sheet.dart'; import '../widgets/record_bottom_sheet.dart';
import 'settings_screen.dart';
class HomeScreen extends StatefulWidget { class HomeScreen extends StatefulWidget {
const HomeScreen({super.key}); const HomeScreen({super.key});
@@ -64,7 +65,17 @@ class _HomeScreenState extends State<HomeScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('SnapLedger')), appBar: AppBar(
title: const Text('SnapLedger'),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const SettingsScreen()),
),
),
],
),
body: Center( body: Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(32), padding: const EdgeInsets.all(32),

View File

@@ -0,0 +1,90 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SettingsScreen extends StatefulWidget {
const SettingsScreen({super.key});
@override
State<SettingsScreen> createState() => _SettingsScreenState();
}
class _SettingsScreenState extends State<SettingsScreen> {
final _serverController = TextEditingController();
final _tokenController = TextEditingController();
bool _initialized = false;
@override
void initState() {
super.initState();
_loadSettings();
}
Future<void> _loadSettings() async {
final prefs = await SharedPreferences.getInstance();
_serverController.text = prefs.getString('server_url') ?? '';
_tokenController.text = prefs.getString('api_token') ?? '';
setState(() => _initialized = true);
}
Future<void> _save() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('server_url', _serverController.text.trim());
await prefs.setString('api_token', _tokenController.text.trim());
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('设置已保存'), duration: Duration(seconds: 1)),
);
Navigator.of(context).pop();
}
@override
void dispose() {
_serverController.dispose();
_tokenController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('设置')),
body: _initialized
? Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: _serverController,
decoration: const InputDecoration(
labelText: '服务器地址',
hintText: 'https://your-server.com',
border: OutlineInputBorder(),
),
keyboardType: TextInputType.url,
),
const SizedBox(height: 16),
TextField(
controller: _tokenController,
decoration: const InputDecoration(
labelText: 'API Token',
hintText: '输入认证令牌',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: FilledButton.icon(
onPressed: _save,
icon: const Icon(Icons.save),
label: const Text('保存'),
),
),
],
),
)
: const Center(child: CircularProgressIndicator()),
);
}
}