Compare commits

...

5 Commits

Author SHA1 Message Date
0874ffa98e seen repaint fixed 2025-08-11 18:01:40 -04:00
b8987e6a8d update struct 2025-08-11 17:35:39 -04:00
1c6d3d6920 menu's for selecting emails 2025-08-11 17:35:29 -04:00
344029d0dd color when hoverred, and seen updated 2025-08-11 17:34:59 -04:00
5d4854901e select emails in bulk and each, select all and unselect 2025-08-09 00:11:29 -04:00
3 changed files with 309 additions and 51 deletions

View File

@ -3,36 +3,134 @@ import 'api_service.dart';
import 'structs.dart';
import 'emailView.dart';
class EmailListScreen extends StatelessWidget {
class EmailListScreen extends StatefulWidget {
final List<GetThreadResponse> emails;
final Future<List<String>> Function(List<String>, String) getEmailContent;
final String folder;
final GlobalKey<_EmailListScreenState> key;
EmailListScreen(
{required this.emails,
{required this.key,
required this.emails,
required this.getEmailContent,
required this.folder});
//fix the email list
required this.folder})
: super(key: key);
@override
_EmailListScreenState createState() => _EmailListScreenState();
}
class _EmailListScreenState extends State<EmailListScreen> {
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;
@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) {
setState(() {
if (selectionType) {
bulkSelectMenu = true;
}
for (int email = 0; email < selectStates.length; email++) {
selectStates[email] = selectionType;
}
});
printTheSelected();
return false;
}
void printTheSelected() {
for (int i = 0; i < selectedEmails.length; i++) {
print(selectedEmails);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.separated(
itemCount: emails.length,
itemCount: widget.emails.length,
itemBuilder: (context, index) {
final email = emails[index];
return ListTile(
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;
if (value!) {
selectedEmails.add(widget.emails[index]);
} else {
selectedEmails.remove(widget.emails[index]);
}
});
},
),
title: Text(email.from_name,
style: TextStyle(fontWeight: FontWeight.bold)),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(email.subject)],
),
trailing: Text(email.date.toString()),
// tileColor: () ,
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
},
),
],
)
: Text(email.date.toString()),
hoverColor: Colors.transparent,
tileColor: seenColour,
onTap: () async {
List<String> emailContent = // list of the html
await getEmailContent(email.messages, folder);
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(
@ -49,7 +147,10 @@ class EmailListScreen extends StatelessWidget {
),
),
);
ApiService().markAsSeen(email.id);
}
},
),
);
},
separatorBuilder: (context, index) => Divider(),
@ -76,6 +177,9 @@ class EmailPageState extends State<EmailPage> {
int page = 1;
bool isBackDisabled = false;
final GlobalKey<_EmailListScreenState> emailListKey =
GlobalKey<_EmailListScreenState>();
@override
void initState() {
super.initState();
@ -84,6 +188,7 @@ class EmailPageState extends State<EmailPage> {
_fetchEmails();
}
List<GetThreadResponse> get getEmails => emails;
String getPage() => widget.page.toString();
bool get backDisabled => isBackDisabled;
@ -114,7 +219,6 @@ class EmailPageState extends State<EmailPage> {
}
});
}
// print(currentPage);
print(widget.page);
_fetchEmails();
}
@ -133,15 +237,20 @@ class EmailPageState extends State<EmailPage> {
}
}
bool selectAllEmails(bool selectionType) {
emailListKey.currentState?.selectAllChecks(selectionType);
return 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
),
);
));
}
}

View File

@ -19,6 +19,16 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
bool _isSidebarOpen = true;
bool querySearches = false;
String? _selectedOption = "INBOX";
List<String> _checkBulk = [
"All",
"None",
"Read",
"Unread",
"Starred",
"Unstarred"
];
bool _checkboxState = false;
bool bulkOptionsState = false;
List<String> _tabs = ['Emails'];
Map<String, Widget> _tabWidgets = {};
@ -307,6 +317,143 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
],
),
),
Container(
padding: EdgeInsets.fromLTRB(0, 4, 0, 4),
color: Theme.of(context).colorScheme.onPrimary,
child: Row(
children: [
Padding(
padding:
const EdgeInsets.fromLTRB(4, 0, 0, 0),
child: Checkbox(
value: _checkboxState,
onChanged: (value) {
setState(() {
_checkboxState = !_checkboxState;
});
if (_checkboxState) {
// var a = _tabWidgets["Emails"].;
print(_emailPageKey.currentState!
.selectAllEmails(
true)); //now i got them all but how do i go down to select them all?
print("all");
bulkOptionsState = true;
} else {
_emailPageKey.currentState!
.selectAllEmails(false);
bulkOptionsState = false;
print("none");
}
}),
),
const SizedBox(
width: 0,
),
PopupMenuButton<String>(
icon: const Icon(
Icons.arrow_drop_down_outlined),
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<String>>[
const PopupMenuItem<String>(
child: Text("All")),
const PopupMenuItem<String>(
child: Text("None")),
const PopupMenuItem<String>(
child: Text("Read")),
const PopupMenuItem<String>(
child: Text("Unread")),
const PopupMenuItem<String>(
child: Text("Starred")),
const PopupMenuItem<String>(
child: Text("Unstarred")),
],
onSelected: (String result) {
print("result $result");
},
),
if (bulkOptionsState) ...<Widget>[
IconButton(
onPressed: null,
icon: Icon(Icons.archive_outlined)),
IconButton(
onPressed: null,
icon: Icon(Icons.delete_outlined)),
IconButton(
onPressed: null,
icon: Icon(
Icons.mark_email_read_outlined)),
IconButton(
onPressed: null,
icon: Icon(
Icons.drive_file_move_outlined)),
],
PopupMenuButton<String>(
icon: const Icon(Icons.more_vert),
itemBuilder: (BuildContext context) {
if (!bulkOptionsState) {
return <PopupMenuEntry<String>>[
const PopupMenuItem<String>(
child: Row(
children: [
Icon(Icons
.mark_email_read_outlined),
const SizedBox(
width: 4.0,
),
Text("Mark all as read")
],
),
),
const PopupMenuDivider(),
PopupMenuItem(
child: Text(
"Select messages to see more actions",
style: TextStyle(
color: Colors
.blueGrey.shade300),
))
];
} else {
return <PopupMenuEntry<String>>[
const PopupMenuItem<String>(
child: Row(
children: [
Icon(Icons
.mark_email_unread_outlined),
const SizedBox(
width: 4.0,
),
Text("Mark as unread")
],
),
),
const PopupMenuItem<String>(
child: Row(
children: [
Icon(Icons.snooze_outlined),
const SizedBox(
width: 4.0,
),
Text("Snooze")
],
),
),
const PopupMenuItem<String>(
child: Row(
children: [
Icon(Icons.star_border_outlined),
const SizedBox(
width: 4.0,
),
Text("Add star")
],
),
),
];
}
}),
],
)),
Container(
color: Color.fromARGB(255, 131, 110, 143),
child: TabBar(

View File

@ -11,6 +11,7 @@ class GetThreadResponse {
final String from_name;
final String from_address;
final List<MailAddress> to;
late bool seen;
GetThreadResponse({
required this.id,
@ -20,6 +21,7 @@ class GetThreadResponse {
required this.from_name,
required this.from_address,
required this.to,
required this.seen,
});
factory GetThreadResponse.fromJson(Map<String, dynamic> json) {
var toList = json['to'] as List<dynamic>;
@ -32,7 +34,7 @@ class GetThreadResponse {
from_name: json['from_name'],
from_address: json['from_address'],
to: toList.map((i) => MailAddress.fromJson(i)).toList(),
);
seen: json['seen']);
}
}