338 lines
11 KiB
Dart
338 lines
11 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:markdown/markdown.dart' as md;
|
|
import 'api_service.dart';
|
|
import 'structs.dart';
|
|
import 'emailView.dart';
|
|
|
|
class EmailListScreen extends StatefulWidget {
|
|
final List<GetThreadResponse> emails;
|
|
final Future<List<String>> Function(List<String>, String) getEmailContent;
|
|
final String folder;
|
|
final GlobalKey<_EmailListScreenState> key;
|
|
final Function(List<GetThreadResponse>)? 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<EmailListScreen>
|
|
with TickerProviderStateMixin {
|
|
late List<bool> selectStates; // for checkboxes if its selected or not
|
|
late List<GetThreadResponse> selectedEmails =
|
|
[]; // holds the emails that are selected i.e. the emails that got the checkbox on
|
|
final Set<int> _hoveredRows = {}; //the row that is being hovered over atm
|
|
bool bulkSelectMenu = false;
|
|
final GlobalKey<EmailPageState> _emailPageKey = GlobalKey<EmailPageState>();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
selectStates = List<bool>.filled(widget.emails.length, false);
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(covariant EmailListScreen oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (oldWidget.emails.length != widget.emails.length) {
|
|
selectStates = List<bool>.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<GetThreadResponse> 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<String> 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");
|
|
} 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<GetThreadResponse>)? onSelectionChanged;
|
|
|
|
EmailPage({Key? key, this.onSelectionChanged}) : super(key: key);
|
|
|
|
@override
|
|
EmailPageState createState() => EmailPageState();
|
|
}
|
|
|
|
class EmailPageState extends State<EmailPage> {
|
|
final ApiService apiService = ApiService();
|
|
List<GetThreadResponse> emails = [];
|
|
ValueNotifier<int> currentPageNotifier = ValueNotifier<int>(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<GetThreadResponse> 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<GetThreadResponse> 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<GetThreadResponse> 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,
|
|
));
|
|
}
|
|
}
|