NotSooFriendly94

home_screen.dart

Apr 9th, 2024
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Dart 20.36 KB | Source Code | 0 0
  1. import 'package:flutter/material.dart';
  2. import 'package:intl/intl.dart';
  3. import 'package:flutter_local_notifications/flutter_local_notifications.dart';
  4. import 'package:path_provider/path_provider.dart';
  5. import 'dart:convert';
  6. import 'dart:io';
  7. import 'package:metaballs/metaballs.dart'; // Import Metaballs package
  8.  
  9. class Reminder {
  10.   String name;
  11.   String priority;
  12.   DateTime? dueDate;
  13.  
  14.   Reminder({required this.name, required this.priority, this.dueDate});
  15. }
  16.  
  17. class HomeScreen extends StatefulWidget {
  18.   const HomeScreen({Key? key}) : super(key: key);
  19.  
  20.   @override
  21.   _HomeScreenState createState() => _HomeScreenState();
  22. }
  23.  
  24. class _HomeScreenState extends State<HomeScreen> {
  25.   final TextEditingController _reminderController = TextEditingController();
  26.   DateTime? selectedDate;
  27.   List<Reminder> reminders = [];
  28.   final ScrollController _scrollController = ScrollController();
  29.   bool _fadeInCompleted = false;
  30.   String _selectedFilter = 'Due Date';
  31.  
  32.   FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
  33.       FlutterLocalNotificationsPlugin();
  34.  
  35.   @override
  36.   void initState() {
  37.     super.initState();
  38.     _scrollController.addListener(_onScroll);
  39.     Future.delayed(const Duration(milliseconds: 1000), () {
  40.       _startFadeInAnimation();
  41.     });
  42.  
  43.     var initializationSettingsAndroid =
  44.         const AndroidInitializationSettings('@mipmap/ic_launcher');
  45.     var initializationSettings =
  46.         InitializationSettings(android: initializationSettingsAndroid);
  47.     flutterLocalNotificationsPlugin.initialize(initializationSettings);
  48.  
  49.     _loadReminders();
  50.   }
  51.  
  52.   @override
  53.   void dispose() {
  54.     _scrollController.removeListener(_onScroll);
  55.     _scrollController.dispose();
  56.     super.dispose();
  57.   }
  58.  
  59.   void _onScroll() {
  60.     setState(() {
  61.       // You can implement scrolling logic here if needed
  62.     });
  63.   }
  64.  
  65.   void _showNotification(String title, String body) async {
  66.   var androidPlatformChannelSpecifics = const AndroidNotificationDetails(
  67.     'your channel id',
  68.     'your channel name',
  69.     importance: Importance.max,
  70.     priority: Priority.high,
  71.     ticker: 'ticker',
  72.   );
  73.   var platformChannelSpecifics = NotificationDetails(
  74.     android: androidPlatformChannelSpecifics,
  75.   );
  76.   await flutterLocalNotificationsPlugin.show(
  77.     0,
  78.     title,
  79.     body,
  80.     platformChannelSpecifics,
  81.   );
  82. }
  83.  
  84.   void _startFadeInAnimation() {
  85.     Future.delayed(const Duration(milliseconds: 1000), () {
  86.       setState(() {
  87.         _fadeInCompleted = true;
  88.       });
  89.     });
  90.   }
  91.  
  92.  void _loadReminders() async {
  93.   final appDocumentsDirectory = await getApplicationDocumentsDirectory();
  94.   final String directoryPath = '${appDocumentsDirectory.path}/Reminders';
  95.   print('Searching for JSON files in directory: $directoryPath');
  96.   final Directory directory = Directory(directoryPath);
  97.  
  98.   if (directory.existsSync()) {
  99.     final List<FileSystemEntity> files = directory.listSync();
  100.     print('List of JSON files in directory:');
  101.    
  102.     for (final file in files) {
  103.       if (file is File && file.path.endsWith('.json')) {
  104.         print('File path: ${file.path}');
  105.         final String fileContents = await file.readAsString();
  106.         final Map<String, dynamic> reminderDetails = jsonDecode(fileContents) as Map<String, dynamic>;
  107.        
  108.         final String reminderName = reminderDetails['name'];
  109.         final String priority = reminderDetails['priority'];
  110.         final String dateString = reminderDetails['dueDate'];
  111.         final DateTime? dueDate = DateTime.tryParse(dateString);
  112.        
  113.         if (reminderName != null && priority != null && dueDate != null) {
  114.           setState(() {
  115.             final reminder = Reminder(
  116.               name: reminderName,
  117.               priority: priority,
  118.               dueDate: dueDate,
  119.             );
  120.             reminders.add(reminder);
  121.           });
  122.         }
  123.       }
  124.     }
  125.    
  126.     // Sort reminders immediately after loading
  127.     _sortReminders();
  128.   }
  129. }
  130.  
  131. DateTime? _parseDueDate(String dateString) {
  132.   try {
  133.     final List<String> dateParts = dateString.split('_');
  134.     if (dateParts.length == 3) {
  135.       final int day = int.parse(dateParts[0]);
  136.       final int month = int.parse(dateParts[1]);
  137.       final int year = int.parse(dateParts[2]);
  138.       return DateTime(year, month, day);
  139.     }
  140.   } catch (e) {
  141.     print('Error parsing due date: $e');
  142.   }
  143.   return null;
  144. }
  145.  
  146.   void _addReminder(DateTime selectedDate) async {
  147.   final newReminder = _reminderController.text.trim();
  148.   if (newReminder.isNotEmpty) {
  149.     setState(() {
  150.       final reminder = Reminder(
  151.         name: newReminder,
  152.         priority: 'Normal', // Default priority
  153.         dueDate: selectedDate,
  154.       );
  155.       reminders.add(reminder);
  156.       _scheduleNotification(newReminder, selectedDate);
  157.       _reminderController.clear();
  158.       _sortReminders(); // Sort reminders after adding a new one
  159.     });
  160.  
  161.     // Prepare reminder details
  162.     final reminderDetails = <String, dynamic>{
  163.       'name': newReminder,
  164.       'priority': 'Normal', // Default priority
  165.       'dueDate': DateFormat('dd_MM_yyyy').format(selectedDate), // Convert DateTime to formatted string
  166.     };
  167.  
  168.     // Convert reminderDetails map to JSON string
  169.     final jsonString = jsonEncode(reminderDetails);
  170.  
  171.     // Print JSON string
  172.     print('Reminder details to be saved to JSON file: $jsonString');
  173.  
  174.     // Save reminder details to JSON file
  175.     _saveReminderToFileAsync(reminderDetails);
  176.  
  177.     // Print file path and name
  178.     final appDocumentsDirectory = await getApplicationDocumentsDirectory();
  179.     final String directoryPath = '${appDocumentsDirectory.path}/Reminders';
  180.     final fileName = '${reminderDetails['name']}_${reminderDetails['dueDate']}.json';
  181.     print('Reminder details saved to: $directoryPath/$fileName');
  182.   } else {
  183.     // Show a styled Snackbar if reminder text is empty
  184.     ScaffoldMessenger.of(context).showSnackBar(
  185.       SnackBar(
  186.         behavior: SnackBarBehavior.floating,
  187.         elevation: 0,
  188.         content: Container(
  189.           height: 40,
  190.           alignment: Alignment.center,
  191.           padding: const EdgeInsets.symmetric(horizontal: 16.0),
  192.           decoration: BoxDecoration(
  193.             color: const Color.fromARGB(133, 255, 0, 0),
  194.             borderRadius: BorderRadius.circular(20),
  195.             border: Border.all(color: Colors.white),
  196.           ),
  197.           child: const Text(
  198.             'Please enter a reminder',
  199.             textAlign: TextAlign.center,
  200.             style: TextStyle(
  201.               color: Colors.white,
  202.               fontSize: 15,
  203.             ),
  204.           ),
  205.         ),
  206.         duration: const Duration(seconds: 4),
  207.         margin: const EdgeInsets.only(bottom: 20),
  208.       ),
  209.     );
  210.   }
  211. }
  212.  
  213.   Future<void> _saveReminderToFileAsync(Map<String, dynamic> reminderDetails) async {
  214.     final appDocumentsDirectory = await getApplicationDocumentsDirectory();
  215.     final String directoryPath = '${appDocumentsDirectory.path}/Reminders';
  216.     final Directory directory = Directory(directoryPath);
  217.  
  218.     // Create directory if it doesn't exist
  219.     if (!directory.existsSync()) {
  220.       directory.createSync(recursive: true);
  221.       print('Directory created: $directoryPath');
  222.     }
  223.  
  224.     // Generate filename
  225.     final String fileName = '${reminderDetails['name']}_${reminderDetails['dueDate']}.json';
  226.     final File file = File('$directoryPath/$fileName');
  227.     await file.writeAsString(jsonEncode(reminderDetails));
  228.     print('Reminder details saved to: ${file.path}');
  229.   }
  230.  
  231.   void _updateReminderInFile(Reminder oldReminder, Reminder newReminder) async {
  232.   final appDocumentsDirectory = await getApplicationDocumentsDirectory();
  233.   final String directoryPath = '${appDocumentsDirectory.path}/Reminders';
  234.   final Directory directory = Directory(directoryPath);
  235.   if (directory.existsSync()) {
  236.     final List<FileSystemEntity> files = directory.listSync();
  237.     for (final file in files) {
  238.       if (file is File) {
  239.         final String fileContents = await file.readAsString();
  240.         final Map<String, dynamic> reminderDetails =
  241.             jsonDecode(fileContents) as Map<String, dynamic>;
  242.         if (reminderDetails['name'] == oldReminder.name) {
  243.           reminderDetails['name'] = newReminder.name;
  244.           reminderDetails['priority'] = newReminder.priority;
  245.           // Avoid unnecessary conversion to ISO 8601 format here
  246.           reminderDetails['dueDate'] = DateFormat('dd_MM_yyyy').format(newReminder.dueDate!);
  247.           await file.writeAsString(jsonEncode(reminderDetails));
  248.           print('File Successfully updated: ${file.path}');
  249.           break;
  250.         }
  251.       }
  252.     }
  253.   }
  254. }
  255.  
  256.   void _deleteReminderFile(Reminder reminder) async {
  257.     final appDocumentsDirectory = await getApplicationDocumentsDirectory();
  258.     final String directoryPath = '${appDocumentsDirectory.path}/Reminders';
  259.     final String fileName =
  260.         '${reminder.name}_${DateFormat('dd_MM_yyyy').format(reminder.dueDate!)}.json';
  261.     final File file = File('$directoryPath/$fileName');
  262.     if (file.existsSync()) {
  263.       await file.delete();
  264.       print('Reminder details deleted: ${file.path}');
  265.     } else {
  266.       print('Reminder details file does not exist: ${file.path}');
  267.     }
  268.   }
  269.  
  270.   void _scheduleNotification(String reminder, DateTime dueDate) {
  271.     final now = DateTime.now();
  272.     final difference = dueDate.difference(now);
  273.     final seconds = difference.inSeconds;
  274.     final notificationTime = now.add(Duration(seconds: seconds));
  275.  
  276.     _showNotification(reminder, 'Reminder: $reminder');
  277.   }
  278.  
  279.   void _sortReminders() {
  280.   setState(() {
  281.     if (_selectedFilter == 'Due Date') {
  282.       reminders.sort((a, b) => a.dueDate!.compareTo(b.dueDate!));
  283.     } else {
  284.       reminders.sort((a, b) {
  285.         if (a.priority == b.priority) {
  286.           return 0;
  287.         } else if (a.priority == 'High') {
  288.           return -1;
  289.         } else if (b.priority == 'High') {
  290.           return 1;
  291.         } else if (a.priority == 'Normal') {
  292.           return -1;
  293.         } else {
  294.           return 1;
  295.         }
  296.       });
  297.     }
  298.   });
  299. }
  300.  
  301. Color _getReminderTileColor(String priority) {
  302.   switch (priority) {
  303.     case 'Low':
  304.       return const Color.fromARGB(167, 0, 255, 8); // Transparent green
  305.     case 'Normal':
  306.       return const Color.fromARGB(184, 0, 140, 255); // Transparent blue
  307.     case 'High':
  308.       return const Color.fromARGB(164, 255, 17, 0); // Transparent red
  309.     default:
  310.       return const Color.fromARGB(184, 0, 140, 255); // Transparent blue (Default)
  311.   }
  312. }
  313.  
  314.  @override
  315. Widget build(BuildContext context) {
  316.   return Metaballs(
  317.     color: const Color.fromARGB(255, 66, 133, 244),
  318.     effect: MetaballsEffect.follow(
  319.       growthFactor: 1,
  320.       smoothing: 1,
  321.       radius: 0.5,
  322.     ),
  323.     gradient: const LinearGradient(
  324.       colors: [Color.fromARGB(160, 17, 0, 113), Color.fromARGB(173, 128, 0, 255)],
  325.       begin: Alignment.bottomRight,
  326.       end: Alignment.topLeft,
  327.     ),
  328.     metaballs: 20,
  329.     animationDuration: const Duration(milliseconds: 200),
  330.     speedMultiplier: 1,
  331.     bounceStiffness: 3,
  332.     minBallRadius: 30,
  333.     maxBallRadius: 60,
  334.     glowRadius: 0.7,
  335.     glowIntensity: 0.6,
  336.     child: AnimatedOpacity(
  337.       opacity: _fadeInCompleted ? 1.0 : 0.0,
  338.       duration: const Duration(milliseconds: 1500),
  339.       child: Scaffold(
  340.         backgroundColor: const Color.fromARGB(103, 145, 145, 145),
  341.         appBar: AppBar(
  342.           backgroundColor: const Color.fromARGB(0, 145, 145, 145),
  343.           title: const Text(
  344.             'Home Reminders',
  345.             style: TextStyle(color: Colors.white),
  346.           ),
  347.           centerTitle: true,
  348.         ),
  349.         body: Padding(
  350.           padding: const EdgeInsets.all(16.0),
  351.           child: Column(
  352.             crossAxisAlignment: CrossAxisAlignment.start,
  353.             children: [
  354.               TextField(
  355.                 controller: _reminderController,
  356.                 decoration: const InputDecoration(
  357.                   hintText: 'Enter Reminder',
  358.                   hintStyle: TextStyle(color: Colors.white, fontSize: 20),
  359.                 ),
  360.                 onChanged: (_) {
  361.                   setState(() {});
  362.                 },
  363.                 style: const TextStyle(color: Colors.white, fontSize: 20.0),
  364.               ),
  365.               const SizedBox(height: 20),
  366.               Row(
  367.                 children: [
  368.                   Expanded(
  369.                     child: ElevatedButton(
  370.                       onPressed: () async {
  371.                         final pickedDate = await showDatePicker(
  372.                           context: context,
  373.                           initialDate: DateTime.now(),
  374.                           firstDate: DateTime.now(),
  375.                           lastDate: DateTime(2100),
  376.                         );
  377.                         if (pickedDate != null) {
  378.                           setState(() {
  379.                             selectedDate = pickedDate;
  380.                           });
  381.                         }
  382.                       },
  383.                       style: ElevatedButton.styleFrom(
  384.                         foregroundColor: Colors.white,
  385.                         backgroundColor: const Color.fromARGB(100, 132, 58, 217),
  386.                         shape: RoundedRectangleBorder(
  387.                           borderRadius: BorderRadius.circular(10),
  388.                           side: const BorderSide(color: Color.fromARGB(255, 132, 58, 217)),
  389.                         ),
  390.                       ),
  391.                       child: Text(
  392.                         selectedDate == null
  393.                             ? 'Select Due Date'
  394.                             : DateFormat('dd/MM/yyyy').format(selectedDate!),
  395.                         style: const TextStyle(fontSize: 17),
  396.                       ),
  397.                     ),
  398.                   ),
  399.                   const SizedBox(width: 20),
  400.                   ElevatedButton(
  401.                     onPressed: () {
  402.                       if (selectedDate != null) {
  403.                         _addReminder(selectedDate!);
  404.                       } else {
  405.                         ScaffoldMessenger.of(context).showSnackBar(
  406.                           SnackBar(
  407.                             content: Text('Please select a due date first'),
  408.                             duration: Duration(seconds: 2),
  409.                           ),
  410.                         );
  411.                       }
  412.                     },
  413.                     style: ElevatedButton.styleFrom(
  414.                       foregroundColor: Colors.white,
  415.                       backgroundColor: const Color.fromARGB(100, 132, 58, 217),
  416.                       shape: RoundedRectangleBorder(
  417.                         borderRadius: BorderRadius.circular(10),
  418.                         side: const BorderSide(color: Color.fromARGB(255, 132, 58, 217)),
  419.                       ),
  420.                     ),
  421.                     child: const Text(
  422.                       'Add Reminder',
  423.                       style: TextStyle(fontSize: 17),
  424.                     ),
  425.                   ),
  426.                 ],
  427.               ),
  428.               const SizedBox(height: 70),
  429.               Row(
  430.                 children: [
  431.                   Expanded(
  432.                     child: DropdownButton<String>(
  433.                       value: _selectedFilter,
  434.                       onChanged: (String? newValue) {
  435.                         setState(() {
  436.                           _selectedFilter = newValue!;
  437.                           _sortReminders();
  438.                         });
  439.                       },
  440.                       dropdownColor: const Color.fromARGB(100, 132, 58, 217),
  441.                       style: const TextStyle(color: Colors.white, fontSize: 20),
  442.                       iconSize: 30,
  443.                       iconEnabledColor: Colors.white,
  444.                       iconDisabledColor: Colors.white,
  445.                       items: <String>['Due Date', 'Importance'].map<DropdownMenuItem<String>>(
  446.                         (String value) {
  447.                           return DropdownMenuItem<String>(
  448.                             value: value,
  449.                             child: Text(value),
  450.                           );
  451.                         },
  452.                       ).toList(),
  453.                     ),
  454.                   ),
  455.                 ],
  456.               ),
  457.               const SizedBox(height: 30),
  458.               const Text(
  459.                 'Reminders:',
  460.                 style: TextStyle(
  461.                   fontSize: 20.0,
  462.                   fontWeight: FontWeight.bold,
  463.                   color: Colors.white,
  464.                 ),
  465.               ),
  466.               const SizedBox(height: 10),
  467.               Expanded(
  468.                 child: ListView.builder(
  469.                   controller: _scrollController,
  470.                   itemCount: reminders.length,
  471.                   itemBuilder: (BuildContext context, int index) {
  472.                     final reminder = reminders[index];
  473.                     return Padding(
  474.                       padding: const EdgeInsets.symmetric(vertical: 10.0),
  475.                       child: ClipRRect(
  476.                         borderRadius: BorderRadius.circular(15.0),
  477.                         child: Container(
  478.                           color: _getReminderTileColor(reminder.priority),
  479.                           child: Dismissible(
  480.                             key: UniqueKey(),
  481.                             direction: DismissDirection.horizontal,
  482.                             background: Container(
  483.                               color: Colors.blue,
  484.                               alignment: Alignment.centerLeft,
  485.                               child: const Padding(
  486.                                 padding: EdgeInsets.only(left: 20.0),
  487.                                 child: Icon(Icons.edit, color: Colors.white),
  488.                               ),
  489.                             ),
  490.                             secondaryBackground: Container(
  491.                               color: Colors.red,
  492.                               alignment: Alignment.centerRight,
  493.                               child: const Padding(
  494.                                 padding: EdgeInsets.only(right: 20.0),
  495.                                 child: Icon(Icons.delete, color: Colors.white),
  496.                               ),
  497.                             ),
  498.                             onDismissed: (direction) {
  499.                               setState(() {
  500.                                 reminders.removeAt(index);
  501.                                 _deleteReminderFile(reminder);
  502.                               });
  503.                             },
  504.                             child: ListTile(
  505.                               title: Text(reminder.name, style: const TextStyle(color: Colors.white, fontSize: 20)),
  506.                               subtitle: Text(
  507.                                 reminder.dueDate != null
  508.                                     ? 'Due Date: ${DateFormat('dd/MM/yyyy').format(reminder.dueDate!)}'
  509.                                     : 'Due Date: Not set',
  510.                                 style: const TextStyle(color: Colors.white, fontSize: 15),
  511.                               ),
  512.                               trailing: DropdownButton<String>(
  513.                                 iconSize: 30,
  514.                                 dropdownColor: const Color.fromARGB(170, 132, 58, 217),
  515.                                 value: reminder.priority,
  516.                                 onChanged: (String? newValue) {
  517.                                   setState(() {
  518.                                     reminder.priority = newValue!;
  519.                                     _updateReminderInFile(reminder, reminder);
  520.                                   });
  521.                                 },
  522.                                 items: <String>['Low', 'Normal', 'High'].map<DropdownMenuItem<String>>(
  523.                                   (String value) {
  524.                                     return DropdownMenuItem<String>(
  525.                                       value: value,
  526.                                       child: Text(value, style: const TextStyle(color: Colors.white, fontSize: 20)),
  527.                                     );
  528.                                   },
  529.                                 ).toList(),
  530.                               ),
  531.                             ),
  532.                           ),
  533.                         ),
  534.                       ),
  535.                     );
  536.                   },
  537.                 ),
  538.               ),
  539.             ],
  540.           ),
  541.         ),
  542.       ),
  543.     ),
  544.   );
  545. }
  546.  
  547. }
  548.  
Advertisement
Add Comment
Please, Sign In to add comment