Files
QingTing-Player/lib/pages/webdav_setup_page.dart
T

250 lines
8.2 KiB
Dart

import 'package:flutter/material.dart';
import '../services/webdav_service.dart';
class WebDAVSetupPage extends StatefulWidget {
const WebDAVSetupPage({super.key});
@override
State<WebDAVSetupPage> createState() => _WebDAVSetupPageState();
}
class _WebDAVSetupPageState extends State<WebDAVSetupPage> {
final _formKey = GlobalKey<FormState>();
final _baseUrlController = TextEditingController();
final _usernameController = TextEditingController();
final _passwordController = TextEditingController();
bool _isLoading = false;
bool _isConnected = false;
String _statusText = '未连接';
@override
void initState() {
super.initState();
_loadSavedCredentials();
}
@override
void dispose() {
_baseUrlController.dispose();
_usernameController.dispose();
_passwordController.dispose();
super.dispose();
}
Future<void> _loadSavedCredentials() async {
final hasCred = await WebDAVService.instance.loadCredentials();
setState(() {
_isConnected = hasCred;
_statusText = hasCred ? '已连接' : '未连接';
if (hasCred) {
_baseUrlController.text = WebDAVService.instance._baseUrl ?? '';
// 用户名不显示,保持隐私
}
});
}
Future<void> _connect() async {
if (!_formKey.currentState!.validate()) return;
setState(() => _isLoading = true);
try {
await WebDAVService.instance.saveCredentials(
_baseUrlController.text.trim(),
_usernameController.text.trim(),
_passwordController.text.trim(),
);
// 尝试列出文件以验证连接
await WebDAVService.instance.getMusicFiles();
setState(() {
_isConnected = true;
_statusText = '已连接';
_isLoading = false;
});
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('✅ WebDAV 连接成功'),
backgroundColor: Color(0xFF4CAF50),
),
);
Navigator.pop(context, true);
}
} catch (e) {
setState(() {
_isConnected = false;
_statusText = '连接失败';
_isLoading = false;
});
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('❌ 连接失败: $e'),
backgroundColor: Colors.red,
),
);
}
}
}
Future<void> _disconnect() async {
await WebDAVService.instance.clearCredentials();
setState(() {
_isConnected = false;
_statusText = '未连接';
});
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('已断开连接'),
backgroundColor: Colors.grey,
),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF0E1211),
appBar: AppBar(
title: const Text('WebDAV 设置'),
backgroundColor: Colors.transparent,
elevation: 0,
foregroundColor: Colors.white,
),
body: Padding(
padding: const EdgeInsets.all(24),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 状态显示
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: const Color(0xFF1A2A2A),
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(
_isConnected ? Icons.cloud_done : Icons.cloud_off,
color:
_isConnected ? const Color(0xFF4CAF50) : Colors.grey,
),
const SizedBox(width: 12),
Text(
'状态: $_statusText',
style: TextStyle(
color: _isConnected
? const Color(0xFF4CAF50)
: Colors.grey[400],
),
),
const Spacer(),
if (_isConnected)
TextButton(
onPressed: _disconnect,
style:
TextButton.styleFrom(foregroundColor: Colors.red),
child: const Text('断开'),
),
],
),
),
const SizedBox(height: 24),
// 表单
TextFormField(
controller: _baseUrlController,
enabled: !_isConnected,
style: const TextStyle(color: Colors.white),
decoration: const InputDecoration(
labelText: 'WebDAV 地址',
labelStyle: TextStyle(color: Colors.grey),
hintText: 'https://nas.local/dav/',
hintStyle: TextStyle(color: Colors.grey),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFFB8D4D0)),
),
),
validator: (v) =>
v == null || v.isEmpty ? '请输入 WebDAV 地址' : null,
),
const SizedBox(height: 16),
TextFormField(
controller: _usernameController,
enabled: !_isConnected,
style: const TextStyle(color: Colors.white),
decoration: const InputDecoration(
labelText: '用户名',
labelStyle: TextStyle(color: Colors.grey),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFFB8D4D0)),
),
),
validator: (v) => v == null || v.isEmpty ? '请输入用户名' : null,
),
const SizedBox(height: 16),
TextFormField(
controller: _passwordController,
enabled: !_isConnected,
obscureText: true,
style: const TextStyle(color: Colors.white),
decoration: const InputDecoration(
labelText: '密码',
labelStyle: TextStyle(color: Colors.grey),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFFB8D4D0)),
),
),
validator: (v) => v == null || v.isEmpty ? '请输入密码' : null,
),
const SizedBox(height: 32),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed:
_isConnected ? null : (_isLoading ? null : _connect),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFB8D4D0),
foregroundColor: Colors.black87,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: _isLoading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.black87,
),
)
: Text(_isConnected ? '已连接' : '连接'),
),
),
],
),
),
),
);
}
}