import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; class StorageService { static const String _keyServerUrl = 'server_url'; static const String _keyToken = 'token'; static const String _keyPlexToken = 'plex_token'; static const String _keyServerData = 'server_data'; static const String _keyClientId = 'client_identifier'; static const String _keySelectedLibraryIndex = 'selected_library_index'; static const String _keyLibraryFilters = 'library_filters'; static const String _keyUserProfile = 'user_profile'; static StorageService? _instance; late SharedPreferences _prefs; StorageService._(); static Future getInstance() async { if (_instance == null) { _instance = StorageService._(); await _instance!._init(); } return _instance!; } Future _init() async { _prefs = await SharedPreferences.getInstance(); } // Server URL Future saveServerUrl(String url) async { await _prefs.setString(_keyServerUrl, url); } String? getServerUrl() { return _prefs.getString(_keyServerUrl); } // Server Access Token Future saveToken(String token) async { await _prefs.setString(_keyToken, token); } String? getToken() { return _prefs.getString(_keyToken); } // Alias for server access token for clarity Future saveServerAccessToken(String token) async { await saveToken(token); } String? getServerAccessToken() { return getToken(); } // Plex.tv Token (for API access) Future savePlexToken(String token) async { await _prefs.setString(_keyPlexToken, token); } String? getPlexToken() { return _prefs.getString(_keyPlexToken); } // Server Data (full PlexServer object as JSON) Future saveServerData(Map serverJson) async { final jsonString = json.encode(serverJson); await _prefs.setString(_keyServerData, jsonString); } Map? getServerData() { final jsonString = _prefs.getString(_keyServerData); if (jsonString == null) return null; try { return json.decode(jsonString) as Map; } catch (e) { return null; } } // Client Identifier Future saveClientIdentifier(String clientId) async { await _prefs.setString(_keyClientId, clientId); } String? getClientIdentifier() { return _prefs.getString(_keyClientId); } // Save all credentials at once Future saveCredentials({ required String serverUrl, required String token, required String clientIdentifier, }) async { await Future.wait([ saveServerUrl(serverUrl), saveToken(token), saveClientIdentifier(clientIdentifier), ]); } // Check if credentials exist bool hasCredentials() { return getServerUrl() != null && getToken() != null; } // Clear all credentials Future clearCredentials() async { await Future.wait([ _prefs.remove(_keyServerUrl), _prefs.remove(_keyToken), _prefs.remove(_keyPlexToken), _prefs.remove(_keyServerData), _prefs.remove(_keyClientId), _prefs.remove(_keyUserProfile), ]); } // Get all credentials as a map Map getCredentials() { return { 'serverUrl': getServerUrl(), 'token': getToken(), 'clientIdentifier': getClientIdentifier(), }; } // Selected Library Index Future saveSelectedLibraryIndex(int index) async { await _prefs.setInt(_keySelectedLibraryIndex, index); } int? getSelectedLibraryIndex() { return _prefs.getInt(_keySelectedLibraryIndex); } // Library Filters (stored as JSON string) Future saveLibraryFilters(Map filters) async { final jsonString = json.encode(filters); await _prefs.setString(_keyLibraryFilters, jsonString); } Map getLibraryFilters() { final jsonString = _prefs.getString(_keyLibraryFilters); if (jsonString == null) return {}; try { final decoded = json.decode(jsonString) as Map; return decoded.map((key, value) => MapEntry(key, value.toString())); } catch (e) { return {}; } } // Clear library preferences Future clearLibraryPreferences() async { await Future.wait([ _prefs.remove(_keySelectedLibraryIndex), _prefs.remove(_keyLibraryFilters), ]); } // User Profile (stored as JSON string) Future saveUserProfile(Map profileJson) async { final jsonString = json.encode(profileJson); await _prefs.setString(_keyUserProfile, jsonString); } Map? getUserProfile() { final jsonString = _prefs.getString(_keyUserProfile); if (jsonString == null) return null; try { return json.decode(jsonString) as Map; } catch (e) { return null; } } }