Main coves client
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}