1/// Environment Configuration for Coves Mobile 2/// 3/// Supports multiple environments: 4/// - Production: Real Bluesky infrastructure (prod flavor) 5/// - Local: Local PDS + PLC for development/testing (dev flavor) 6/// 7/// Environment is determined by (in priority order): 8/// 1. --dart-define=ENVIRONMENT=local/production (explicit override) 9/// 2. Flutter flavor (dev -> local, prod -> production) 10/// 3. Default: production 11enum Environment { production, local } 12 13class EnvironmentConfig { 14 const EnvironmentConfig({ 15 required this.environment, 16 required this.apiUrl, 17 required this.handleResolverUrl, 18 required this.plcDirectoryUrl, 19 }); 20 final Environment environment; 21 final String apiUrl; 22 final String handleResolverUrl; 23 final String plcDirectoryUrl; 24 25 /// Production configuration (default) 26 /// Uses Coves production server with public atproto infrastructure 27 static const production = EnvironmentConfig( 28 environment: Environment.production, 29 apiUrl: 'https://coves.social', 30 handleResolverUrl: 31 'https://bsky.social/xrpc/com.atproto.identity.resolveHandle', 32 plcDirectoryUrl: 'https://plc.directory', 33 ); 34 35 /// Local development configuration 36 /// Uses localhost via adb reverse port forwarding 37 /// 38 /// IMPORTANT: Before testing, run these commands to forward ports: 39 /// adb reverse tcp:3001 tcp:3001 # PDS 40 /// adb reverse tcp:3002 tcp:3002 # PLC 41 /// adb reverse tcp:8081 tcp:8081 # AppView 42 /// 43 /// Note: For physical devices not connected via USB, use ngrok URLs instead 44 static const local = EnvironmentConfig( 45 environment: Environment.local, 46 apiUrl: 'http://localhost:8081', 47 handleResolverUrl: 48 'http://localhost:3001/xrpc/com.atproto.identity.resolveHandle', 49 plcDirectoryUrl: 'http://localhost:3002', 50 ); 51 52 /// Flutter flavor passed via --flavor flag 53 /// This is set automatically by Flutter build system 54 static const String _flavor = String.fromEnvironment('FLUTTER_FLAVOR'); 55 56 /// Explicit environment override via --dart-define=ENVIRONMENT=local 57 /// Also supports --dart-define=ENV=dev for convenience 58 static const String _envOverride = String.fromEnvironment('ENVIRONMENT'); 59 static const String _envShorthand = String.fromEnvironment('ENV'); 60 61 /// Get current environment based on build configuration 62 /// 63 /// Priority: 64 /// 1. Explicit --dart-define=ENVIRONMENT=local/production 65 /// 2. Flavor: dev -> local, prod -> production 66 /// 3. Default: production 67 static EnvironmentConfig get current { 68 // Priority 1: Explicit environment override 69 if (_envOverride.isNotEmpty) { 70 switch (_envOverride) { 71 case 'local': 72 return local; 73 case 'production': 74 return production; 75 } 76 } 77 78 // Priority 1b: Shorthand ENV override (dev -> local, prod -> production) 79 if (_envShorthand.isNotEmpty) { 80 switch (_envShorthand) { 81 case 'dev': 82 case 'local': 83 return local; 84 case 'prod': 85 case 'production': 86 return production; 87 } 88 } 89 90 // Priority 2: Flavor-based environment 91 switch (_flavor) { 92 case 'dev': 93 return local; 94 case 'prod': 95 return production; 96 } 97 98 // Default: production 99 return production; 100 } 101 102 /// Get the current flavor name for display purposes 103 static String get flavorName { 104 if (_flavor.isNotEmpty) { 105 return _flavor; 106 } 107 if (_envOverride == 'local') { 108 return 'dev'; 109 } 110 return 'prod'; 111 } 112 113 bool get isProduction => environment == Environment.production; 114 bool get isLocal => environment == Environment.local; 115}