- Introduced a new `logSafe` function for consistent logging with sensitivity handling. - Replaced direct logger calls with `logSafe` in `api_service.dart`, `app_initializer.dart`, `auth_service.dart`, `permission_service.dart`, and `my_image_compressor.dart`. - Enhanced error handling and logging in various service methods to capture exceptions and provide more context. - Updated image compression logging to include quality and size metrics. - Improved app initialization logging to capture success and error states. - Ensured sensitive information is not logged directly.
		
			
				
	
	
		
			113 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:get/get.dart';
 | |
| import 'package:marco/helpers/services/app_logger.dart';
 | |
| import 'package:marco/helpers/services/api_service.dart';
 | |
| import 'package:marco/helpers/theme/theme_customizer.dart';
 | |
| import 'package:marco/model/project_model.dart';
 | |
| 
 | |
| class LayoutController extends GetxController {
 | |
|   // Theme Customization
 | |
|   ThemeCustomizer themeCustomizer = ThemeCustomizer();
 | |
| 
 | |
|   // Global Keys
 | |
|   final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
 | |
|   final GlobalKey<State<StatefulWidget>> scrollKey = GlobalKey();
 | |
| 
 | |
|   // Scroll
 | |
|   final ScrollController scrollController = ScrollController();
 | |
| 
 | |
|   // Reactive State
 | |
|   final RxBool isLoading = true.obs;
 | |
|   final RxBool isLoadingProjects = true.obs;
 | |
|   final RxBool isProjectSelectionExpanded = true.obs;
 | |
|   final RxBool isProjectListExpanded = false.obs;
 | |
|   final RxBool isProjectDropdownExpanded = false.obs;
 | |
|   final RxList<ProjectModel> projects = <ProjectModel>[].obs;
 | |
|   final RxMap<String, RxBool> uploadingStates = <String, RxBool>{}.obs;
 | |
| 
 | |
|   // Selected Project
 | |
|   RxString? selectedProjectId;
 | |
| 
 | |
|   bool isLastIndex = false;
 | |
| 
 | |
|   @override
 | |
|   void onInit() {
 | |
|     super.onInit();
 | |
|     fetchProjects();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void onReady() {
 | |
|     super.onReady();
 | |
|     ThemeCustomizer.addListener(onChangeTheme);
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void dispose() {
 | |
|     ThemeCustomizer.removeListener(onChangeTheme);
 | |
|     scrollController.dispose();
 | |
|     super.dispose();
 | |
|   }
 | |
| 
 | |
|   /// Fetch project list from API and initialize the selection.
 | |
|   Future<void> fetchProjects() async {
 | |
|     isLoading.value = true;
 | |
|     isLoadingProjects.value = true;
 | |
| 
 | |
|     try {
 | |
|       final response = await ApiService.getProjects();
 | |
| 
 | |
|       if (response != null && response.isNotEmpty) {
 | |
|         final fetchedProjects = response.map((json) => ProjectModel.fromJson(json)).toList();
 | |
|         projects.assignAll(fetchedProjects);
 | |
|         selectedProjectId = RxString(fetchedProjects.first.id.toString());
 | |
| 
 | |
|         logSafe("Projects fetched: ${fetchedProjects.length}", level: LogLevel.info);
 | |
|       } else {
 | |
|         logSafe("No projects found or API call failed.", level: LogLevel.warning);
 | |
|       }
 | |
|     } catch (e, st) {
 | |
|       logSafe("Error fetching projects", level: LogLevel.error, error: e, stackTrace: st);
 | |
|     }
 | |
| 
 | |
|     isLoadingProjects.value = false;
 | |
|     isLoading.value = false;
 | |
|     update(['dashboard_controller']);
 | |
|   }
 | |
| 
 | |
|   /// Update selected project ID
 | |
|   void updateSelectedProject(String projectId) {
 | |
|     selectedProjectId?.value = projectId;
 | |
|     logSafe("Selected project updated", level: LogLevel.info);
 | |
|   }
 | |
| 
 | |
|   /// Toggle expansion of the project list section
 | |
|   void toggleProjectListExpanded() {
 | |
|     isProjectListExpanded.toggle();
 | |
|     logSafe("Project list expanded: ${isProjectListExpanded.value}", level: LogLevel.debug);
 | |
|   }
 | |
| 
 | |
|   /// Handle theme changes (light/dark, drawer toggles)
 | |
|   void onChangeTheme(ThemeCustomizer oldVal, ThemeCustomizer newVal) {
 | |
|     themeCustomizer = newVal;
 | |
|     update();
 | |
| 
 | |
|     if (newVal.rightBarOpen) {
 | |
|       scaffoldKey.currentState?.openEndDrawer();
 | |
|       logSafe("Theme changed — end drawer opened", level: LogLevel.debug);
 | |
|     } else {
 | |
|       scaffoldKey.currentState?.closeEndDrawer();
 | |
|       logSafe("Theme changed — end drawer closed", level: LogLevel.debug);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /// Optional notification toggles (placeholder)
 | |
|   void enableNotificationShade() {
 | |
|     logSafe("Notification shade enabled (not implemented)", level: LogLevel.verbose);
 | |
|   }
 | |
| 
 | |
|   void disableNotificationShade() {
 | |
|     logSafe("Notification shade disabled (not implemented)", level: LogLevel.verbose);
 | |
|   }
 | |
| }
 |