Files
notepad/lib/screens/settings_screen.dart

205 lines
6.0 KiB
Dart

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 _urlController = TextEditingController();
final _keyController = TextEditingController();
bool _isSaving = false;
bool _obscureKey = true;
static const _urlPrefKey = 'server_url';
static const _apiKeyPrefKey = 'api_key';
@override
void initState() {
super.initState();
_loadSettings();
}
@override
void dispose() {
_urlController.dispose();
_keyController.dispose();
super.dispose();
}
Future<void> _loadSettings() async {
final prefs = await SharedPreferences.getInstance();
_urlController.text = prefs.getString(_urlPrefKey) ?? '';
_keyController.text = prefs.getString(_apiKeyPrefKey) ?? '';
}
Future<void> _saveSettings() async {
setState(() => _isSaving = true);
try {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_urlPrefKey, _urlController.text.trim());
await prefs.setString(_apiKeyPrefKey, _keyController.text.trim());
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Settings saved')),
);
Navigator.pop(context, true); // true = settings changed
}
} finally {
if (mounted) setState(() => _isSaving = false);
}
}
Future<void> _clearSettings() async {
final confirmed = await showDialog<bool>(
context: context,
builder: (_) => AlertDialog(
title: const Text('Clear settings?'),
content: const Text('Server URL and API key will be removed.'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('Clear', style: TextStyle(color: Colors.red)),
),
],
),
);
if (confirmed == true) {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_urlPrefKey);
await prefs.remove(_apiKeyPrefKey);
_urlController.clear();
_keyController.clear();
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Settings cleared')),
);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Backup settings'),
actions: [
IconButton(
icon: const Icon(Icons.delete_outline),
tooltip: 'Clear settings',
onPressed: _clearSettings,
),
],
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.secondaryContainer,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(
Icons.info_outline,
color: Theme.of(context).colorScheme.onSecondaryContainer,
size: 20,
),
const SizedBox(width: 8),
Expanded(
child: Text(
'Point to your running Python server. '
'Leave blank to use local storage only.',
style: TextStyle(
color: Theme.of(context).colorScheme.onSecondaryContainer,
fontSize: 13,
),
),
),
],
),
),
const SizedBox(height: 24),
TextField(
controller: _urlController,
keyboardType: TextInputType.url,
autocorrect: false,
decoration: const InputDecoration(
labelText: 'Server URL',
hintText: 'http://192.168.1.x:8000',
prefixIcon: Icon(Icons.dns_outlined),
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
TextField(
controller: _keyController,
obscureText: _obscureKey,
autocorrect: false,
enableSuggestions: false,
decoration: InputDecoration(
labelText: 'API Key',
hintText: 'Your X-API-Key value',
prefixIcon: const Icon(Icons.key_outlined),
border: const OutlineInputBorder(),
suffixIcon: IconButton(
icon: Icon(
_obscureKey
? Icons.visibility_outlined
: Icons.visibility_off_outlined,
),
onPressed: () => setState(() => _obscureKey = !_obscureKey),
),
),
),
const SizedBox(height: 32),
FilledButton.icon(
onPressed: _isSaving ? null : _saveSettings,
icon: _isSaving
? const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.save_outlined),
label: Text(_isSaving ? 'Saving...' : 'Save'),
),
],
),
);
}
}
class AppSettings {
static const _urlPrefKey = 'server_url';
static const _apiKeyPrefKey = 'api_key';
static Future<({String url, String apiKey})> load() async {
final prefs = await SharedPreferences.getInstance();
return (
url: prefs.getString(_urlPrefKey) ?? '',
apiKey: prefs.getString(_apiKeyPrefKey) ?? '',
);
}
static bool isConfigured({required String url, required String apiKey}) {
return url.isNotEmpty && apiKey.isNotEmpty;
}
}