Description
Description
Problem
- A few files (like
add_or_update_alarm_view.dart
) have grown to over 1000 lines of code - As discussed with @MarkisDev, this needs modularization for better code organization
- The floating action button implementation contains business logic mixed with UI code
- This leads to
- Reduced code maintainability
- Harder to test individual components
- Difficult to reuse components
- Increased cognitive load for developers
- The large file size and mixed concerns make the code harder to maintain and understand
Proposed Solution
- Extract the floating action button into a separate widget component
- Implement proper separation of concerns
- Create a clean, reusable Floating Action Button widget
Benefits of This Refactoring
-
Separation of Concerns
- UI logic is separated from business logic
- Button appearance and behavior are encapsulated
- Permissions checking is handled cleanly
-
Improved Maintainability
- Smaller, focused components
- Clear responsibilities for each class
- Easier to test individual components
-
Better Reusability
- Floating Action Button widget can be reused across the app
- Consistent styling and behavior
- Configurable through parameters
-
Code Organization
- Reduced file size in main view
- Better folder structure
- Clearer component boundaries
Here's the implementation:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:ultimate_alarm_clock/app/utils/constants.dart';
import 'package:ultimate_alarm_clock/app/utils/utils.dart';
import '../controllers/add_or_update_alarm_controller.dart';
import 'package:ultimate_alarm_clock/app/modules/settings/controllers/theme_controller.dart';
class SaveOrUpdateFloatingActionButton extends GetView<AddOrUpdateAlarmController> {
const SaveOrUpdateFloatingActionButton({
Key? key,
required this.onSavePressed,
}) : super(key: key);
final Future<void> Function() onSavePressed;
@override
Widget build(BuildContext context) {
final themeController = Get.find<ThemeController>();
final width = MediaQuery.of(context).size.width;
final height = MediaQuery.of(context).size.height;
return Obx(
() => controller.mutexLock.value
? const SizedBox()
: Padding(
padding: const EdgeInsets.all(18.0),
child: SizedBox(
height: height * 0.06,
width: width * 0.8,
child: TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(kprimaryColor),
),
onPressed: () async {
Utils.hapticFeedback();
await _handleButtonPress();
},
child: Text(
_getButtonText(),
style: Theme.of(context).textTheme.displaySmall!.copyWith(
color: themeController.secondaryTextColor.value,
),
),
),
),
),
);
}
String _getButtonText() {
return controller.alarmRecord.value.alarmID.isEmpty
? 'Save'.tr
: 'Update'.tr;
}
Future<void> _handleButtonPress() async {
await controller.checkOverlayPermissionAndNavigate();
if (!await _checkRequiredPermissions()) return;
await onSavePressed();
}
Future<bool> _checkRequiredPermissions() async {
return await Permission.systemAlertWindow.isGranted &&
await Permission.ignoreBatteryOptimizations.isGranted;
}
}
Usage in Original File
Replace the existing Floating Action Button code in add_or_update_alarm_view.dart
with:
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: SaveOrUpdateFloatingActionButton(
onSavePressed: () async {
if (!controller.homeController.isProfile.value) {
await _handleAlarmSave();
} else if (controller.profileTextEditingController.text.isNotEmpty) {
controller.createProfile();
}
},
),
Screenshots
No response