import 'package:flutter/material.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; // import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; //TODO: copy hope_page.dart impl of iframe import 'dart:ui_web' as ui; import 'dart:html' as html; // import 'package:flutter_html/flutter_html.dart'; class MailAddress { final String? name; final String address; MailAddress({this.name, required this.address}); factory MailAddress.fromJson(Map json) { return MailAddress( name: json['name'], address: json['address'], ); } } class SerializableMessage { final String name; final String from; final List to; final List cc; final String hash; // final String path; final String subject; final String date; final int uid; final String list; final String id; final String in_reply_to; SerializableMessage({ required this.name, required this.from, required this.to, required this.cc, required this.hash, required this.subject, required this.date, required this.uid, required this.list, required this.id, required this.in_reply_to, }); factory SerializableMessage.fromJson(Map json) { var toList = json['to'] as List; var ccList = json['cc'] as List; return SerializableMessage( name: json['name'], from: json['from'], // to: json['name', 'address'] to: toList.map((i) => MailAddress.fromJson(i)).toList(), cc: ccList.map((i) => MailAddress.fromJson(i)).toList(), // path: json['path'], hash: json['hash'], subject: json['subject'], date: json['date'], uid: json['uid'], list: json['list'], id: json['id'], in_reply_to: json['in_reply_to'], ); } } class EmailPage extends StatefulWidget { const EmailPage({super.key}); final String title = 'Emails'; @override State createState() => _EmailPageState(); } class _EmailPageState extends State { List emails = []; void _displayEmailsFromFolder(String folder) async { // Map> messagesMap = {}; List allEmails = []; try { var url = Uri.http( '127.0.0.1:3001', 'sorted_threads_by_date', {'folder': folder}); var response = await http.get(url); // print(response.body); // Map json = jsonDecode(response.body); original // json.forEach((key, value) { // List messages = (value as List) // .map((item) => SerializableMessage.fromJson(item)) // .toList(); // messagesMap[key] = messages; // }); // new shit if (response.statusCode == 200) { List json = jsonDecode(response.body); for (var item in json) { if (item.length > 1 && item[0] is String && item[1] is List) { // print('Date: ${item[0]}, Threads: ${item[1]}'); List threadIDs = List.from(item[1]); for (var threadId in threadIDs) { await fetchThreadMessages(threadId, allEmails); } } } } else { throw Exception('Failed to load threads'); } } catch (e) { print('_displayEmailsFromFolder caught error: $e'); } setState(() { emails.clear(); // emails = messagesMap.values.toList().expand((list) => list).toList(); emails.addAll(allEmails); print(emails); ; }); } Future fetchThreadMessages( int threadId, List allEmails) async { try { var url = Uri.http( '127.0.0.1:3001', 'get_thread_messages', {'id': threadId.toString()}); var response = await http.get(url); if (response.statusCode == 200) { List messagesJson = jsonDecode(response.body); List messages = messagesJson.map((mj) => SerializableMessage.fromJson(mj)).toList(); allEmails.addAll(messages); } else { throw Exception( 'Failed to fetch thread messages for thread ID: $threadId'); } } catch (e) { print('Error fetching thread messages: $e'); } } Future _getEmailContent(String relativePath) async { String content = r""" """; try { var url = Uri.http('127.0.0.1:3001', 'email', {'path': relativePath}); var response = await http.get(url); if (response.statusCode == 200) { print('ok'); content = response.body; } } catch (e) { print('_getEmailContent caught error: $e'); } // print(content); return content; } Future> _getDrawerItems() async { List drawerItems = []; try { var url = Uri.http('127.0.0.1:3001', 'folders'); var response = await http.get(url); drawerItems = List.from(json.decode(response.body)); } catch (e) { print('_getDrawerItems caught error: $e'); } List drawerWidgets = []; for (String item in drawerItems) { drawerWidgets.add( ListTile( leading: Icon(Icons.mail), title: Text(item), onTap: () { _displayEmailsFromFolder(item); Navigator.pop(context); }, ), ); } return drawerWidgets; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), drawer: Drawer( child: FutureBuilder>( future: _getDrawerItems(), // call the async function to get the future builder: (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { // While data is loading, show a progress indicator return Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { // If something went wrong, show an error message return Center(child: Text('Error: ${snapshot.error}')); } else { // When data is fetched successfully, display the items return ListView( padding: EdgeInsets.zero, children: snapshot.data!, // Unwrap the data once confirmed it's there ); } }, ), ), body: EmailListScreen(emails: emails, getEmailContent: _getEmailContent), ); } } class EmailListScreen extends StatelessWidget { List emails; final Future Function(String) getEmailContent; EmailListScreen({required this.emails, required this.getEmailContent}); @override Widget build(BuildContext context) { print(emails); return Scaffold( appBar: AppBar( title: Text('Emails'), ), body: ListView.separated( itemCount: emails.length, itemBuilder: (context, index) { return ListTile( title: Text(emails[index].from, style: TextStyle(fontWeight: FontWeight.bold)), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(emails[index].subject), ], ), trailing: Text(emails[index].date.toString()), onTap: () async { String emailContent = await getEmailContent(emails[index].path); Navigator.push( context, MaterialPageRoute( builder: (context) => EmailView(emailContent: emailContent)), ); }); }, separatorBuilder: (context, index) { return Divider(); }, ), ); } } class EmailView extends StatefulWidget { final String emailContent; const EmailView({Key? key, required this.emailContent}) : super(key: key); @override _EmailViewState createState() => _EmailViewState(); // @override // void initState(){ // ui.platformViewRegistry.registerViewFactory( // 'html-view33', // (int viewId) => html.IFrameElement() // ..width = '100%' // ..height = '100%' // ..srcdoc = emailContent // ..style.border = 'none'); } // @override // Widget build(BuildContext context) { // return Scaffold( // appBar: AppBar( // title: Text('Email Content'), // ), // // body: SingleChildScrollView( // // child: Padding( // // padding: const EdgeInsets.all(16.0), // // child: HtmlWidget( // // emailContent, // // onErrorBuilder: (context, element, error) => // // Text('$element error: $error'), // // onLoadingBuilder: (context, element, loadingProgress) => // // CircularProgressIndicator(), // // renderMode: RenderMode.column, // // // webView: true, // // ), // // ), // // ), // // body: Center( // // child: Html( // // data: emailContent // // ) // // , // // ), // body: Center( // child: HtmlElementView(viewType: 'html-view33',), // ), // ); // } // } // class HtmlContentWidget // class HtmlIFrameView extends StatelessWidget { // final String emailContent; // const HtmlIFrameView({required this.emailContent}); // @override // Widget build(BuildContext context) { // return HtmlElementView(viewType: 'html-view'); // } // } // class HtmlElementView extends StatelessWidget { // final String emailContent; // const HtmlElementView({required this.emailContent}); // @override // Widget build(BuildContext context) { // return IFrameElementWidget(emailContent: emailContent); // } // } // class IFrameElementWidget extends StatelessWidget { // final String emailContent; // const IFrameElementWidget({required this.emailContent}); // @override // Widget build(BuildContext context) { // ui.platformViewRegistry.registerViewFactory( // 'html-view', // (int viewId) => html.IFrameElement() // ..width = '100%' // ..height = '100%' // ..srcdoc = emailContent // ..style.border = 'none', // ); // return HtmlElementView( // viewType: 'html-view', // ); // } // } class _EmailViewState extends State { @override void initState() { super.initState(); ui.platformViewRegistry.registerViewFactory( 'html-view33', (int viewId) => html.IFrameElement() ..width = '100%' ..height = '100%' ..srcdoc = widget.emailContent ..style.border = 'none', ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('email content'), ), body: HtmlElementView( viewType: 'html-view33', ), ); } }