// lib/remote/remote_settings.dart import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; class RemoteSettings { static const _storage = FlutterSecureStorage( aOptions: AndroidOptions( encryptedSharedPreferences: true, resetOnError: true, // auto-reset della singola voce cifrata se fallisce la decrittazione ), ); static const _kEnabled = 'remote_enabled'; static const _kBaseUrl = 'remote_base_url'; static const _kIndexPath = 'remote_index_path'; static const _kEmail = 'remote_email'; static const _kPassword = 'remote_password'; static final bool defaultEnabled = kDebugMode ? true : false; static final String defaultBaseUrl = kDebugMode ? 'https://prova.patachina.it' : ''; static final String defaultIndexPath = kDebugMode ? 'photos/' : ''; static final String defaultEmail = kDebugMode ? 'fabio@gmail.com' : ''; static final String defaultPassword = kDebugMode ? 'master66' : ''; bool enabled; String baseUrl; String indexPath; String email; String password; RemoteSettings({ required this.enabled, required this.baseUrl, required this.indexPath, required this.email, required this.password, }); // 🔎 helper: leggi una chiave in modo “safe” e, se fallisce, cancella solo quella static Future _readKeySafe(String key) async { try { return await _storage.read(key: key); } on PlatformException { // solo questa chiave è corrotta → la pulisco await _storage.delete(key: key); return null; } } // 🧼 helper: rimuove caratteri invisibili/di controllo tipici che “sporcano” gli URL static String _sanitizeUrl(String s) { // rimuove BOM, LRM/RLM e altri ‘format characters’ comuni negli incolla const _invisibles = r'[\u200B-\u200F\u202A-\u202E\u2060-\u2064\uFEFF]'; final cleaned = s.replaceAll(RegExp(_invisibles), ''); return cleaned.trim(); } static Future load() async { // legge *per singola chiave* con fallback ai default final enabledStr = await _readKeySafe(_kEnabled); final rawBase = await _readKeySafe(_kBaseUrl); final indexPath = await _readKeySafe(_kIndexPath) ?? defaultIndexPath; final email = await _readKeySafe(_kEmail) ?? defaultEmail; final password = await _readKeySafe(_kPassword) ?? defaultPassword; final enabled = (enabledStr ?? (defaultEnabled ? 'true' : 'false')) == 'true'; // sanitize della base URL (toglie caratteri non alfabetici “invisibili”) final baseUrl = _sanitizeUrl(rawBase ?? defaultBaseUrl); return RemoteSettings( enabled: enabled, baseUrl: baseUrl, indexPath: indexPath, email: email, password: password, ); } Future save() async { // Sanitize prima di salvare, così evitiamo che restino in storage caratteri strani await _storage.write(key: _kEnabled, value: enabled ? 'true' : 'false'); await _storage.write(key: _kBaseUrl, value: _sanitizeUrl(baseUrl)); await _storage.write(key: _kIndexPath, value: indexPath.trim()); await _storage.write(key: _kEmail, value: email.trim()); await _storage.write(key: _kPassword, value: password); } static Future debugSeedIfEmpty() async { if (!kDebugMode) return; Future _seed(String key, String value) async { try { final existing = await _storage.read(key: key); if (existing == null) { await _storage.write(key: key, value: value); } } on PlatformException { // chiave “sporca” → reset di quella sola chiave e poi scrittura await _storage.delete(key: key); await _storage.write(key: key, value: value); } } await _seed(_kEnabled, defaultEnabled ? 'true' : 'false'); await _seed(_kBaseUrl, defaultBaseUrl); await _seed(_kIndexPath, defaultIndexPath); await _seed(_kEmail, defaultEmail); await _seed(_kPassword, defaultPassword); } }