From c3b8ce02a22dbc374d33f0c47e8006e2b2798c62 Mon Sep 17 00:00:00 2001 From: Misaka Date: Thu, 7 May 2026 19:57:28 +0800 Subject: [PATCH] feat: add settings page for URL configuration Co-Authored-By: Claude Opus 4.6 --- lib/pages/settings_page.dart | 104 +++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 lib/pages/settings_page.dart diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart new file mode 100644 index 0000000..f58a7d7 --- /dev/null +++ b/lib/pages/settings_page.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:pad_scanner/services/api_service.dart'; + +class SettingsPage extends StatefulWidget { + const SettingsPage({super.key}); + + @override + State createState() => _SettingsPageState(); +} + +class _SettingsPageState extends State { + final _controller = TextEditingController(); + final _apiService = ApiService(); + bool _saving = false; + + @override + void initState() { + super.initState(); + _loadUrl(); + } + + Future _loadUrl() async { + final prefs = await SharedPreferences.getInstance(); + _controller.text = prefs.getString('api_url') ?? ''; + } + + Future _saveUrl() async { + setState(() => _saving = true); + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('api_url', _controller.text.trim()); + setState(() => _saving = false); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('URL saved')), + ); + } + } + + Future _testConnection() async { + final url = _controller.text.trim(); + if (url.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please enter a URL first')), + ); + return; + } + final ok = await _apiService.sendScanData( + url, + barcode: 'TEST_BARCODE', + codeType: 'TEST', + ); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(ok ? 'Connection OK' : 'Connection failed')), + ); + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Settings')), + body: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + TextField( + controller: _controller, + decoration: const InputDecoration( + labelText: 'API URL', + hintText: 'http://192.168.1.100:8000/scan', + border: OutlineInputBorder(), + ), + keyboardType: TextInputType.url, + ), + const SizedBox(height: 16), + ElevatedButton( + onPressed: _saving ? null : _saveUrl, + child: _saving + ? const SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator(strokeWidth: 2)) + : const Text('Save'), + ), + const SizedBox(height: 8), + OutlinedButton( + onPressed: _testConnection, + child: const Text('Test Connection'), + ), + ], + ), + ), + ); + } +}