// Author: fruit.com.cn import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'app_config.dart'; /// Debug-only runtime server endpoint persisted outside build-time defines. abstract final class ServerEndpoint { /// Preference key used for the runtime server address. static const String preferenceKey = 'dev.api_base_url'; /// Returns a normalized http(s) URL, or null for invalid input. static String? normalize(String? raw) { final value = raw?.trim() ?? ''; final uri = Uri.tryParse(value); if (uri == null || (uri.scheme != 'http' && uri.scheme != 'https') || uri.host.isEmpty) { return null; } return value.replaceFirst(RegExp(r'/+$'), ''); } /// Resolves runtime > dart-define > default using normalized valid values. static String resolve({ required String? stored, required String compiled, required String fallback, }) { return normalize(stored) ?? normalize(compiled) ?? normalize(fallback) ?? fallback; } /// Loads the persisted override before the app creates its ApiClient. /// /// In release builds this returns immediately without reading preferences. static Future load({ bool debug = kDebugMode, SharedPreferencesAsync? preferences, }) async { if (!debug) return; try { final prefs = preferences ?? SharedPreferencesAsync(); final stored = await prefs.getString(preferenceKey); AppConfig.applyRuntimeBaseUrl( resolve( stored: stored, compiled: AppConfig.compiledBaseUrl, fallback: AppConfig.defaultBaseUrl, ), ); } catch (_) { AppConfig.clearRuntimeBaseUrl(); } } /// Persists a normalized runtime endpoint. static Future save( String raw, { SharedPreferencesAsync? preferences, }) async { final normalized = normalize(raw); if (normalized == null) return false; try { await (preferences ?? SharedPreferencesAsync()).setString( preferenceKey, normalized, ); return true; } catch (_) { return false; } } /// Removes the persisted runtime endpoint. static Future clear({SharedPreferencesAsync? preferences}) async { try { await (preferences ?? SharedPreferencesAsync()).remove(preferenceKey); } catch (_) { // Clearing an optional developer override is best effort. } } }