diff --git a/mobile/lib/models/user.dart b/mobile/lib/models/user.dart index 1172bdfe8..b41d75945 100644 --- a/mobile/lib/models/user.dart +++ b/mobile/lib/models/user.dart @@ -23,15 +23,42 @@ class User { email: json['email'] as String, firstName: json['first_name'] as String?, lastName: json['last_name'] as String?, - uiLayout: (json['ui_layout'] as String?) ?? 'dashboard', - // Default to true when key is absent (legacy payloads from older app versions). - // Avoids regressing existing users who would otherwise be incorrectly gated. - aiEnabled: json.containsKey('ai_enabled') - ? (json['ai_enabled'] == true) - : true, + uiLayout: _coerceUiLayout(json['ui_layout'] ?? json['uiLayout']), + aiEnabled: _coerceBool(json['ai_enabled'] ?? json['aiEnabled'], defaultValue: false), ); } + static String _coerceUiLayout(dynamic value) { + if (value is String) { + final layout = value.trim(); + if (layout.isNotEmpty) return layout; + } + return 'dashboard'; + } + + static bool _coerceBool(dynamic value, {required bool defaultValue}) { + if (value == null) { + return defaultValue; + } + + if (value is bool) return value; + if (value is num) return value != 0; + if (value is String) { + switch (value.trim().toLowerCase()) { + case "true": + case "1": + case "yes": + return true; + case "false": + case "0": + case "no": + return false; + } + } + + return defaultValue; + } + User copyWith({ String? id, String? email, diff --git a/mobile/lib/screens/main_navigation_screen.dart b/mobile/lib/screens/main_navigation_screen.dart index 7b537667e..7a5a05f14 100644 --- a/mobile/lib/screens/main_navigation_screen.dart +++ b/mobile/lib/screens/main_navigation_screen.dart @@ -52,7 +52,7 @@ class _MainNavigationScreenState extends State { const NavigationDestination( icon: Icon(Icons.chat_bubble_outline), selectedIcon: Icon(Icons.chat_bubble), - label: 'AI Chat', + label: 'Assistant', ), ); diff --git a/mobile/lib/screens/settings_screen.dart b/mobile/lib/screens/settings_screen.dart index 38a996ac8..eb5de49dc 100644 --- a/mobile/lib/screens/settings_screen.dart +++ b/mobile/lib/screens/settings_screen.dart @@ -180,10 +180,17 @@ class _SettingsScreenState extends State { ), // App version - const ListTile( - leading: Icon(Icons.info_outline), - title: Text('App Version'), - subtitle: Text('1.0.0'), + ListTile( + leading: const Icon(Icons.info_outline), + title: const Text('App Version: 0.6.8'), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text(' > ui_layout: ${authProvider.user?.uiLayout}'), + Text(' > ai_enabled: ${authProvider.user?.aiEnabled}'), + ], + ), ), const Divider(), diff --git a/mobile/lib/services/auth_service.dart b/mobile/lib/services/auth_service.dart index 874b63068..98a98f31e 100644 --- a/mobile/lib/services/auth_service.dart +++ b/mobile/lib/services/auth_service.dart @@ -56,7 +56,9 @@ class AuthService { // Store user data - parse once and reuse User? user; if (responseData['user'] != null) { - user = User.fromJson(responseData['user']); + final rawUser = responseData['user']; + _logRawUserPayload('login', rawUser); + user = User.fromJson(rawUser); await _saveUser(user); } @@ -160,7 +162,9 @@ class AuthService { // Store user data - parse once and reuse User? user; if (responseData['user'] != null) { - user = User.fromJson(responseData['user']); + final rawUser = responseData['user']; + _logRawUserPayload('signup', rawUser); + user = User.fromJson(rawUser); await _saveUser(user); } @@ -406,6 +410,7 @@ class AuthService { }); await _saveTokens(tokens); + _logRawUserPayload('sso_exchange', data['user']); final user = User.fromJson(data['user']); await _saveUser(user); @@ -451,6 +456,7 @@ class AuthService { final responseData = jsonDecode(response.body); if (response.statusCode == 200) { + _logRawUserPayload('enable_ai', responseData['user']); final user = User.fromJson(responseData['user']); await _saveUser(user); return { @@ -514,6 +520,23 @@ class AuthService { ); } + void _logRawUserPayload(String source, dynamic userPayload) { + if (userPayload == null) { + LogService.instance.debug('AuthService', '$source user payload: '); + return; + } + + if (userPayload is Map) { + try { + LogService.instance.debug('AuthService', '$source user payload: ${jsonEncode(userPayload)}'); + } catch (_) { + LogService.instance.debug('AuthService', '$source user payload: $userPayload'); + } + } else { + LogService.instance.debug('AuthService', '$source user payload type: ${userPayload.runtimeType}'); + } + } + Future _saveApiKey(String apiKey) async { await _storage.write(key: _apiKeyKey, value: apiKey); await _storage.write(key: _authModeKey, value: 'api_key');