Compare commits
5 Commits
71707bd1c0
...
0874ffa98e
Author | SHA1 | Date | |
---|---|---|---|
0874ffa98e | |||
b8987e6a8d | |||
1c6d3d6920 | |||
344029d0dd | |||
5d4854901e |
195
lib/email.dart
195
lib/email.dart
@ -3,53 +3,154 @@ import 'api_service.dart';
|
|||||||
import 'structs.dart';
|
import 'structs.dart';
|
||||||
import 'emailView.dart';
|
import 'emailView.dart';
|
||||||
|
|
||||||
class EmailListScreen extends StatelessWidget {
|
class EmailListScreen extends StatefulWidget {
|
||||||
final List<GetThreadResponse> emails;
|
final List<GetThreadResponse> emails;
|
||||||
final Future<List<String>> Function(List<String>, String) getEmailContent;
|
final Future<List<String>> Function(List<String>, String) getEmailContent;
|
||||||
final String folder;
|
final String folder;
|
||||||
|
final GlobalKey<_EmailListScreenState> key;
|
||||||
|
|
||||||
EmailListScreen(
|
EmailListScreen(
|
||||||
{required this.emails,
|
{required this.key,
|
||||||
|
required this.emails,
|
||||||
required this.getEmailContent,
|
required this.getEmailContent,
|
||||||
required this.folder});
|
required this.folder})
|
||||||
//fix the email list
|
: 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: ListView.separated(
|
body: ListView.separated(
|
||||||
itemCount: emails.length,
|
itemCount: widget.emails.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final email = emails[index];
|
Color seenColour;
|
||||||
return ListTile(
|
final email = widget.emails[index];
|
||||||
title: Text(email.from_name,
|
if (email.seen) {
|
||||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
seenColour = ThemeData().highlightColor;
|
||||||
subtitle: Column(
|
} else {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
seenColour = Colors.transparent;
|
||||||
children: [Text(email.subject)],
|
}
|
||||||
|
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)],
|
||||||
|
),
|
||||||
|
// 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 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);
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
trailing: Text(email.date.toString()),
|
|
||||||
onTap: () async {
|
|
||||||
List<String> emailContent = // list of the html
|
|
||||||
await getEmailContent(email.messages, folder);
|
|
||||||
|
|
||||||
print(email.messages); //email ids of the thread
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (context, index) => Divider(),
|
separatorBuilder: (context, index) => Divider(),
|
||||||
@ -76,6 +177,9 @@ class EmailPageState extends State<EmailPage> {
|
|||||||
int page = 1;
|
int page = 1;
|
||||||
bool isBackDisabled = false;
|
bool isBackDisabled = false;
|
||||||
|
|
||||||
|
final GlobalKey<_EmailListScreenState> emailListKey =
|
||||||
|
GlobalKey<_EmailListScreenState>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -84,6 +188,7 @@ class EmailPageState extends State<EmailPage> {
|
|||||||
_fetchEmails();
|
_fetchEmails();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<GetThreadResponse> get getEmails => emails;
|
||||||
String getPage() => widget.page.toString();
|
String getPage() => widget.page.toString();
|
||||||
bool get backDisabled => isBackDisabled;
|
bool get backDisabled => isBackDisabled;
|
||||||
|
|
||||||
@ -114,7 +219,6 @@ class EmailPageState extends State<EmailPage> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// print(currentPage);
|
|
||||||
print(widget.page);
|
print(widget.page);
|
||||||
_fetchEmails();
|
_fetchEmails();
|
||||||
}
|
}
|
||||||
@ -133,15 +237,20 @@ class EmailPageState extends State<EmailPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool selectAllEmails(bool selectionType) {
|
||||||
|
emailListKey.currentState?.selectAllChecks(selectionType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: EmailListScreen(
|
body: EmailListScreen(
|
||||||
emails: emails,
|
key: emailListKey,
|
||||||
// getEmailContent: apiService.fetchEmailContent,
|
emails: emails,
|
||||||
getEmailContent: apiService.fetchMarkdownContent,
|
// getEmailContent: apiService.fetchEmailContent,
|
||||||
folder: widget.selectedFolder, //try to grab from it directly
|
getEmailContent: apiService.fetchMarkdownContent,
|
||||||
),
|
folder: widget.selectedFolder, //try to grab from it directly
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,16 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
|||||||
bool _isSidebarOpen = true;
|
bool _isSidebarOpen = true;
|
||||||
bool querySearches = false;
|
bool querySearches = false;
|
||||||
String? _selectedOption = "INBOX";
|
String? _selectedOption = "INBOX";
|
||||||
|
List<String> _checkBulk = [
|
||||||
|
"All",
|
||||||
|
"None",
|
||||||
|
"Read",
|
||||||
|
"Unread",
|
||||||
|
"Starred",
|
||||||
|
"Unstarred"
|
||||||
|
];
|
||||||
|
bool _checkboxState = false;
|
||||||
|
bool bulkOptionsState = false;
|
||||||
|
|
||||||
List<String> _tabs = ['Emails'];
|
List<String> _tabs = ['Emails'];
|
||||||
Map<String, Widget> _tabWidgets = {};
|
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(
|
Container(
|
||||||
color: Color.fromARGB(255, 131, 110, 143),
|
color: Color.fromARGB(255, 131, 110, 143),
|
||||||
child: TabBar(
|
child: TabBar(
|
||||||
|
@ -11,6 +11,7 @@ class GetThreadResponse {
|
|||||||
final String from_name;
|
final String from_name;
|
||||||
final String from_address;
|
final String from_address;
|
||||||
final List<MailAddress> to;
|
final List<MailAddress> to;
|
||||||
|
late bool seen;
|
||||||
|
|
||||||
GetThreadResponse({
|
GetThreadResponse({
|
||||||
required this.id,
|
required this.id,
|
||||||
@ -20,19 +21,20 @@ class GetThreadResponse {
|
|||||||
required this.from_name,
|
required this.from_name,
|
||||||
required this.from_address,
|
required this.from_address,
|
||||||
required this.to,
|
required this.to,
|
||||||
|
required this.seen,
|
||||||
});
|
});
|
||||||
factory GetThreadResponse.fromJson(Map<String, dynamic> json) {
|
factory GetThreadResponse.fromJson(Map<String, dynamic> json) {
|
||||||
var toList = json['to'] as List<dynamic>;
|
var toList = json['to'] as List<dynamic>;
|
||||||
|
|
||||||
return GetThreadResponse(
|
return GetThreadResponse(
|
||||||
id: json['id'],
|
id: json['id'],
|
||||||
messages: List<String>.from(json['messages']),
|
messages: List<String>.from(json['messages']),
|
||||||
subject: json['subject'],
|
subject: json['subject'],
|
||||||
date: DateTime.parse(json['date']),
|
date: DateTime.parse(json['date']),
|
||||||
from_name: json['from_name'],
|
from_name: json['from_name'],
|
||||||
from_address: json['from_address'],
|
from_address: json['from_address'],
|
||||||
to: toList.map((i) => MailAddress.fromJson(i)).toList(),
|
to: toList.map((i) => MailAddress.fromJson(i)).toList(),
|
||||||
);
|
seen: json['seen']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user