import 'package:flutter/material.dart'; import 'package:markdown/markdown.dart' as md; import 'api_service.dart'; import 'structs.dart'; import 'emailView.dart'; import 'Compose.dart'; class EmailListScreen extends StatefulWidget { final List emails; final Future> Function(List, String) getEmailContent; final String folder; final GlobalKey<_EmailListScreenState> key; final Function(List)? onSelectionChanged; EmailListScreen({ required this.key, required this.emails, required this.getEmailContent, required this.folder, this.onSelectionChanged, }) : super(key: key); @override _EmailListScreenState createState() => _EmailListScreenState(); } class _EmailListScreenState extends State with TickerProviderStateMixin { late List selectStates; // for checkboxes if its selected or not late List selectedEmails = []; // holds the emails that are selected i.e. the emails that got the checkbox on final Set _hoveredRows = {}; //the row that is being hovered over atm bool bulkSelectMenu = false; final GlobalKey _emailPageKey = GlobalKey(); @override void initState() { super.initState(); selectStates = List.filled(widget.emails.length, false); } @override void didUpdateWidget(covariant EmailListScreen oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.emails.length != widget.emails.length) { selectStates = List.filled(widget.emails.length, false); } } bool selectAllChecks(bool selectionType) { //perhaps it should return a list of the selected setState(() { selectedEmails = []; if (selectionType) { bulkSelectMenu = true; for (int email = 0; email < selectStates.length; email++) { selectStates[email] = selectionType; selectedEmails.add(widget.emails[email]); } } else { for (int email = 0; email < selectStates.length; email++) { selectStates[email] = selectionType; } selectedEmails = []; } }); widget.onSelectionChanged?.call(selectedEmails); printTheSelected(); return false; } bool markAsRead(bool read) { print("markasread $read"); setState(() { if (read) { //read for (int email = 0; email < selectedEmails.length; email++) { selectedEmails[email].seen = read; ApiService() .markAsSeen(selectedEmails[email].id); //the remote or .json } } else { //unread for (int email = 0; email < selectedEmails.length; email++) { selectedEmails[email].seen = read; ApiService() .markAsUnseen(selectedEmails[email].id); //the remote or .json print(selectedEmails[email].subject); } } }); return false; } bool moveOfSelected(String destinyFolder) { //this should be called from a widget print("move of folder"); setState(() { for (int email = 0; email < selectedEmails.length; email++) { ApiService().moveEmail( widget.folder, selectedEmails[email].id.toString(), destinyFolder); } }); return false; } // Widget moveOfFolderWidget() List listOfSelectedThreads() { return selectedEmails; } void printTheSelected() { for (int i = 0; i < selectedEmails.length; i++) { print(selectedEmails[i].subject); } } @override Widget build(BuildContext context) { return Scaffold( body: ListView.separated( itemCount: widget.emails.length, itemBuilder: (context, index) { Color seenColour; final email = widget.emails[index]; if (email.seen) { seenColour = ThemeData().highlightColor; } else { seenColour = Colors.transparent; } return MouseRegion( onEnter: (_) => setState(() => _hoveredRows.add(index)), onExit: (_) => setState(() => _hoveredRows.remove(index)), child: ListTile( leading: Checkbox( value: selectStates[index], onChanged: (bool? value) { setState(() { //works great selectStates[index] = value ?? false; setState(() { if (value!) { selectedEmails.add(widget.emails[index]); //here i must update the other side _emailPageKey.currentState?.getListOfSelected(); } else { selectedEmails.remove(widget.emails[index]); _emailPageKey.currentState?.getListOfSelected(); } widget.onSelectionChanged?.call(selectedEmails); print(selectedEmails); }); }); }, ), title: Text(email.from_name, style: TextStyle(fontWeight: FontWeight.bold)), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [Text(email.subject)], ), trailing: _hoveredRows.contains(index) ? Row( mainAxisSize: MainAxisSize.min, children: [ IconButton( icon: Icon(Icons.mark_email_read_outlined), onPressed: () { // mark email as read setState(() { widget.emails[index].seen = true; ApiService().markAsSeen(email.id); }); }, ), IconButton( icon: Icon(Icons.delete_outline), onPressed: () { // delete email ApiService().deleteEmail(widget.folder, email.id); }, ), ], ) : Text(email.date.toString()), hoverColor: Colors.transparent, tileColor: seenColour, onTap: () async { List emailContent = // list of the html await widget.getEmailContent(email.messages, widget.folder); // print("thread id? $email.id"); yes print(email.messages); //email ids of the thread if (widget.folder == "Drafts") { print("IN DRAFTS MOVE THE CONTENT TO THE WRITING THING"); //open the compose OverlayService _thisInstance = OverlayService(); _thisInstance.draftID = email; _thisInstance.showPersistentWidget(context); } else { Navigator.push( context, MaterialPageRoute( // could call collapsable and inside collable each calls email view? builder: (context) => EmailView( emailContent: emailContent, from: email.from_address, name: email.from_name, to: email.to.toString(), subject: email.subject, date: email.date.toString(), id: email.id.toString(), //i think this is thread id? messages: email.messages, ), ), ); ApiService().markAsSeen(email.id); } }, ), ); }, separatorBuilder: (context, index) => Divider(), ), ); } } // ignore: must_be_immutable class EmailPage extends StatefulWidget { String selectedFolder = "INBOX"; //starter int offset = 0; int page = 1; final Function(List)? onSelectionChanged; EmailPage({Key? key, this.onSelectionChanged}) : super(key: key); @override EmailPageState createState() => EmailPageState(); } class EmailPageState extends State { final ApiService apiService = ApiService(); List emails = []; ValueNotifier currentPageNotifier = ValueNotifier(1); int page = 1; bool isBackDisabled = false; final GlobalKey<_EmailListScreenState> emailListKey = GlobalKey<_EmailListScreenState>(); @override void initState() { super.initState(); widget.page = page; isBackDisabled = true; _fetchEmails(); } List get getEmails => emails; String getPage() => widget.page.toString(); bool get backDisabled => isBackDisabled; void updateSelectedFolder(String folder) { setState(() { widget.selectedFolder = folder; }); print(folder); _fetchEmails(); } void updatePagenation(String option) { if (option == "next") { setState(() { widget.offset += 50; widget.page += 1; currentPageNotifier.value = widget.page; isBackDisabled = false; }); } else if (option == "back") { setState(() { widget.offset -= 50; widget.page -= 1; currentPageNotifier.value = widget.page; if (widget.page == 1) { isBackDisabled = true; print("back disabled"); } }); } print(widget.page); _fetchEmails(); } void _fetchEmails() async { try { List fetchedEmails = await apiService .fetchEmailsFromFolder(widget.selectedFolder, widget.offset); if (!mounted) return; setState(() { emails = fetchedEmails; // Update the list of emails }); } catch (e) { print('Error fetching emails: $e'); } } bool selectAllEmails(bool selectionType) { emailListKey.currentState?.selectAllChecks(selectionType); return selectionType; } bool markSelectedAsRead(bool selectionType) { emailListKey.currentState?.markAsRead(selectionType); return selectionType; } bool moveSelectedOfFolder(String folder) { emailListKey.currentState?.moveOfSelected(folder); return false; } List getListOfSelected() { return emailListKey.currentState!.listOfSelectedThreads(); } // return [GetThreadResponse(id: 1, messages: [], subject: "subject", date: DateTime(2025), from_name: "from_name", from_address: "from_address", to: [], seen: false)]; @override Widget build(BuildContext context) { return Scaffold( body: EmailListScreen( key: emailListKey, emails: emails, // getEmailContent: apiService.fetchEmailContent, getEmailContent: apiService.fetchMarkdownContent, folder: widget.selectedFolder, //try to grab from it directly onSelectionChanged: widget.onSelectionChanged, )); } }