import 'package:webdav_client/webdav_client.dart'; import 'package:shared_preferences/shared_preferences.dart'; class WebDAVService { static const String _keyBaseUrl = 'webdav_base_url'; static const String _keyUsername = 'webdav_username'; static const String _keyPassword = 'webdav_password'; static WebDAVService? _instance; static WebDAVService get instance => _instance ??= WebDAVService._(); WebDAVService._(); WebDAVClient? _client; String? _baseUrl; bool get isConnected => _client != null; // 保存凭据 Future saveCredentials( String baseUrl, String username, String password) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString(_keyBaseUrl, baseUrl); await prefs.setString(_keyUsername, username); await prefs.setString(_keyPassword, password); _baseUrl = baseUrl; _client = WebDAVClient( baseUri: Uri.parse(baseUrl), credentials: '$username:$password', ); } // 加载已保存的凭据 Future loadCredentials() async { final prefs = await SharedPreferences.getInstance(); final baseUrl = prefs.getString(_keyBaseUrl); final username = prefs.getString(_keyUsername); final password = prefs.getString(_keyPassword); if (baseUrl != null && username != null && password != null) { _baseUrl = baseUrl; _client = WebDAVClient( baseUri: Uri.parse(baseUrl), credentials: '$username:$password', ); return true; } return false; } // 清除凭据 Future clearCredentials() async { final prefs = await SharedPreferences.getInstance(); await prefs.remove(_keyBaseUrl); await prefs.remove(_keyUsername); await prefs.remove(_keyPassword); _client = null; _baseUrl = null; } // 获取音乐文件列表(仅 .mp3 .flac .m4a .ape .wav) Future> getMusicFiles({String path = '/'}) async { if (_client == null) throw Exception('WebDAV 未连接'); final items = await _client!.listAll(recursive: true); final musicExtensions = ['.mp3', '.flac', '.m4a', '.ape', '.wav', '.opus']; return items .where((item) => item.isFile && musicExtensions.any((ext) => item.path.toLowerCase().endsWith(ext))) .map((item) => WebDAVFileItem( path: item.path, name: item.path.split('/').last, size: item.size, modified: item.modified, )) .toList(); } // 获取文件的完整下载 URL(用于播放) String getFileUrl(String path) { if (_baseUrl == null) throw Exception('WebDAV 未配置'); // 确保 baseUrl 末尾有 '/' final base = _baseUrl!.endsWith('/') ? _baseUrl! : '$_baseUrl/'; // 去掉路径开头的 '/' final cleanPath = path.startsWith('/') ? path.substring(1) : path; return '$base$cleanPath'; } } class WebDAVFileItem { final String path; final String name; final int? size; final DateTime? modified; WebDAVFileItem({ required this.path, required this.name, this.size, this.modified, }); }