HyM attachments resolve: #2 #3
					 5 changed files with 371 additions and 92 deletions
				
			
		| 
						 | 
					@ -1,20 +1,29 @@
 | 
				
			||||||
// this file should handle most of the API calls
 | 
					// this file should handle most of the API calls
 | 
				
			||||||
// it also builds some widgets, but it will be modulated later
 | 
					// it also builds some widgets, but it will be modulated later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:crab_ui/structs.dart';
 | 
					import 'dart:async';
 | 
				
			||||||
 | 
					import 'dart:typed_data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:pointer_interceptor/pointer_interceptor.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'structs.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:http/http.dart' as http;
 | 
					import 'package:http/http.dart' as http;
 | 
				
			||||||
import 'dart:convert';
 | 
					import 'dart:convert';
 | 
				
			||||||
import 'dart:ui_web' as ui;
 | 
					import 'dart:ui_web' as ui;
 | 
				
			||||||
import 'augment.dart';
 | 
					import 'augment.dart';
 | 
				
			||||||
import 'dart:html' as html;
 | 
					import 'dart:html' as html;
 | 
				
			||||||
 | 
					import 'dart:js' as js;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ApiService {
 | 
					class ApiService {
 | 
				
			||||||
  static String ip = "";
 | 
					  static String ip = "";
 | 
				
			||||||
  static String port = "";
 | 
					  static String port = "";
 | 
				
			||||||
 | 
					  static List<AttachmentResponse> threadAttachments = [];
 | 
				
			||||||
 | 
					  static String currFolder = "";
 | 
				
			||||||
 | 
					  static List<String> currThread = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<List<GetThreadResponse>> fetchEmailsFromFolder(
 | 
					  Future<List<GetThreadResponse>> fetchEmailsFromFolder(
 | 
				
			||||||
      String folder, int pagenitaion) async {
 | 
					      String folder, int pagenitaion) async {
 | 
				
			||||||
    // print(ip + " " + port);
 | 
					 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      var url = Uri.http('$ip:$port', 'sorted_threads_by_date', {
 | 
					      var url = Uri.http('$ip:$port', 'sorted_threads_by_date', {
 | 
				
			||||||
        'folder': folder,
 | 
					        'folder': folder,
 | 
				
			||||||
| 
						 | 
					@ -51,8 +60,8 @@ class ApiService {
 | 
				
			||||||
      int threadId,
 | 
					      int threadId,
 | 
				
			||||||
      List<GetThreadResponse> allEmails) async {
 | 
					      List<GetThreadResponse> allEmails) async {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      var url =
 | 
					      var url = Uri.http('${ApiService.ip}:${ApiService.port}', 'get_thread',
 | 
				
			||||||
          Uri.http('$ip:$port', 'get_thread', {'id': threadId.toString()});
 | 
					          {'id': threadId.toString()});
 | 
				
			||||||
      var response = await http.get(url);
 | 
					      var response = await http.get(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (response.statusCode == 200) {
 | 
					      if (response.statusCode == 200) {
 | 
				
			||||||
| 
						 | 
					@ -97,24 +106,34 @@ class ApiService {
 | 
				
			||||||
    return [];
 | 
					    return [];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<String> fetchEmailContent(List<String> IDs) async {
 | 
					  //returns the html for the email, it gets used in emailView
 | 
				
			||||||
 | 
					  Future<String> fetchEmailContent(
 | 
				
			||||||
 | 
					      List<String> IDsString, String emailFolder) async {
 | 
				
			||||||
    String content = r"""
 | 
					    String content = r"""
 | 
				
			||||||
    """;
 | 
					    """;
 | 
				
			||||||
 | 
					    threadAttachments = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      //attaches email after email from a thread
 | 
					      //attaches email after email from a thread
 | 
				
			||||||
      for (var id in IDs) {
 | 
					      for (var id in IDsString) {
 | 
				
			||||||
        var url = Uri.http('$ip:$port', 'email', {'id': id});
 | 
					        var url = Uri.http('$ip:$port', 'email', {'id': id});
 | 
				
			||||||
 | 
					 | 
				
			||||||
        var response = await http.get(url);
 | 
					        var response = await http.get(url);
 | 
				
			||||||
 | 
					        currThread.add(id);
 | 
				
			||||||
        if (response.statusCode == 200) {
 | 
					        if (response.statusCode == 200) {
 | 
				
			||||||
          content += response.body;
 | 
					          content += response.body;
 | 
				
			||||||
          try {
 | 
					          try {
 | 
				
			||||||
            getAttachmentsInfo("INBOX", id);
 | 
					            List<AttachmentInfo> attachments = await getAttachmentsInfo(
 | 
				
			||||||
 | 
					                emailFolder, id);
 | 
				
			||||||
 | 
					            for (var attachment in attachments) {
 | 
				
			||||||
 | 
					              //TODO: for each attachment creaate at the bottom a widget for each individual one
 | 
				
			||||||
 | 
					              threadAttachments
 | 
				
			||||||
 | 
					                  .add(await getAttachment(emailFolder, id, attachment.name));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
          } catch (innerError) {
 | 
					          } catch (innerError) {
 | 
				
			||||||
            print('_getAttachment info caught error $innerError');
 | 
					            print('_getAttachment info caught error $innerError');
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					          content +=
 | 
				
			||||||
 | 
					              """<div id="JuanBedarramarker" style="width: 10px; height: 30px;"></div>""";
 | 
				
			||||||
          content += "<hr>";
 | 
					          content += "<hr>";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -200,18 +219,21 @@ class ApiService {
 | 
				
			||||||
  Future<List<AttachmentInfo>> getAttachmentsInfo(
 | 
					  Future<List<AttachmentInfo>> getAttachmentsInfo(
 | 
				
			||||||
      String folder, String email_id) async {
 | 
					      String folder, String email_id) async {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      var url = Uri.http('127.0.0.1:3001', 'get_attachments_info',
 | 
					      var url = Uri.http('$ip:$port', 'get_attachments_info',
 | 
				
			||||||
          {'folder': folder, 'email_id': email_id});
 | 
					          {'folder': folder, 'id': email_id});
 | 
				
			||||||
      print(url);
 | 
					      // print(url);
 | 
				
			||||||
      var response = await http.get(url);
 | 
					      var response = await http.get(url);
 | 
				
			||||||
      print("response $response");
 | 
					      // print("response $response");
 | 
				
			||||||
      if (response.statusCode == 200) {
 | 
					      if (response.statusCode == 200) {
 | 
				
			||||||
        var result = response.body;
 | 
					        var result = response.body;
 | 
				
			||||||
 | 
					        // print(result);
 | 
				
			||||||
        List<dynamic> attachmentList = json.decode(result);
 | 
					        List<dynamic> attachmentList = json.decode(result);
 | 
				
			||||||
        print("attachment list $attachmentList");
 | 
					        // Map<String, dynamic> attachmentList = json.decode(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // print("attachment list $attachmentList");
 | 
				
			||||||
        List<AttachmentInfo> attachments =
 | 
					        List<AttachmentInfo> attachments =
 | 
				
			||||||
            attachmentList.map((al) => AttachmentInfo.fromJson(al)).toList();
 | 
					            attachmentList.map((al) => AttachmentInfo.fromJson(al)).toList();
 | 
				
			||||||
        print("attachments $attachments");
 | 
					        // print("attachments $attachments");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return attachments;
 | 
					        return attachments;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -220,6 +242,93 @@ class ApiService {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return [];
 | 
					    return [];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<AttachmentResponse> getAttachment(
 | 
				
			||||||
 | 
					      String folder, String email_id, String name) async {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      var url = Uri.http('$ip:$port', 'get_attachment',
 | 
				
			||||||
 | 
					          {'folder': folder, 'id': email_id, 'name': name});
 | 
				
			||||||
 | 
					      var response = await http.get(url);
 | 
				
			||||||
 | 
					      if (response.statusCode == 200) {
 | 
				
			||||||
 | 
					        var result = response.body;
 | 
				
			||||||
 | 
					        // print(result);
 | 
				
			||||||
 | 
					        Map<String, dynamic> attachmentData = json.decode(result);
 | 
				
			||||||
 | 
					        AttachmentResponse data = AttachmentResponse.fromJson(attachmentData);
 | 
				
			||||||
 | 
					        print("data $data");
 | 
				
			||||||
 | 
					        return data;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      print("getAttachment failed $e");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return AttachmentResponse(name: "error", data: Uint8List(0));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<List<Map<String, dynamic>>> getMarkerPosition() async {
 | 
				
			||||||
 | 
					    print("maerker called");
 | 
				
			||||||
 | 
					    // JavaScript code embedded as a string
 | 
				
			||||||
 | 
					    String jsCode = '''
 | 
				
			||||||
 | 
					(async function waitForIframeAndMarkers() {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    return await new Promise((resolve) => {
 | 
				
			||||||
 | 
					      const interval = setInterval(() => {
 | 
				
			||||||
 | 
					        console.log("⏳ Checking for iframe...");
 | 
				
			||||||
 | 
					        var iframe = document.getElementsByTagName('iframe')[0];
 | 
				
			||||||
 | 
					        if (iframe && iframe.contentDocument) {
 | 
				
			||||||
 | 
					          console.log("✅ Iframe found!");
 | 
				
			||||||
 | 
					          var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
 | 
				
			||||||
 | 
					          var markers = iframeDoc.querySelectorAll('[id^="JuanBedarramarker"]');
 | 
				
			||||||
 | 
					          if (markers.length > 0) {
 | 
				
			||||||
 | 
					            console.log(`✅ Found markers in the iframe.`);
 | 
				
			||||||
 | 
					            var positions = [];
 | 
				
			||||||
 | 
					            markers.forEach((marker) => {
 | 
				
			||||||
 | 
					              var rect = marker.getBoundingClientRect();
 | 
				
			||||||
 | 
					              positions.push({
 | 
				
			||||||
 | 
					                id: marker.id,
 | 
				
			||||||
 | 
					                x: rect.left + window.scrollX,
 | 
				
			||||||
 | 
					                y: rect.top + window.scrollY,
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            console.log("📌 Marker positions:", positions);
 | 
				
			||||||
 | 
					            clearInterval(interval);
 | 
				
			||||||
 | 
					            resolve(JSON.stringify(positions)); // Ensure proper JSON string
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            console.log("❌ No markers found yet.");
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          console.log("❌ Iframe not found or not loaded yet.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }, 200);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  } catch (error) {
 | 
				
			||||||
 | 
					    console.error("JS Error:", error);
 | 
				
			||||||
 | 
					    throw error; // Propagate error to Dart
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					})();
 | 
				
			||||||
 | 
					''';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      // Execute the JavaScript code using eval
 | 
				
			||||||
 | 
					      final result = await js.context.callMethod('eval', [jsCode]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (result != null && result is String) {
 | 
				
			||||||
 | 
					        print("Result received: $result");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Parse the JSON string returned by JavaScript into a Dart list of maps
 | 
				
			||||||
 | 
					        final List<dynamic> parsedResult = jsonDecode(result);
 | 
				
			||||||
 | 
					        var positions = List<Map<String, dynamic>>.from(parsedResult);
 | 
				
			||||||
 | 
					        print("positions put on");
 | 
				
			||||||
 | 
					        print(positions);
 | 
				
			||||||
 | 
					        return positions;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        print("result is null or not a string");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (e, stackTrace) {
 | 
				
			||||||
 | 
					      print("Error executing JavaScript: $e");
 | 
				
			||||||
 | 
					      print(stackTrace);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return [];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EmailView extends StatefulWidget {
 | 
					class EmailView extends StatefulWidget {
 | 
				
			||||||
| 
						 | 
					@ -246,10 +355,18 @@ class EmailView extends StatefulWidget {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class _EmailViewState extends State<EmailView> {
 | 
					class _EmailViewState extends State<EmailView> {
 | 
				
			||||||
 | 
					  //html css rendering thing
 | 
				
			||||||
  late Key iframeKey;
 | 
					  late Key iframeKey;
 | 
				
			||||||
  late String currentContent;
 | 
					  late String currentContent;
 | 
				
			||||||
  late String viewTypeId;
 | 
					  late String viewTypeId;
 | 
				
			||||||
 | 
					  Future<List<Map<String, dynamic>>>? _markerPositionsFuture;
 | 
				
			||||||
  // TextEditingController _jumpController = TextEditingController();
 | 
					  // TextEditingController _jumpController = TextEditingController();
 | 
				
			||||||
 | 
					  final hardcodedMarkers = [
 | 
				
			||||||
 | 
					    {'id': 'marker1', 'x': 50, 'y': 100},
 | 
				
			||||||
 | 
					    {'id': 'marker2', 'x': 150, 'y': 200},
 | 
				
			||||||
 | 
					    {'id': 'marker3', 'x': 250, 'y': 300},
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					  ApiService _apiService = ApiService();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void initState() {
 | 
					  void initState() {
 | 
				
			||||||
| 
						 | 
					@ -257,6 +374,7 @@ class _EmailViewState extends State<EmailView> {
 | 
				
			||||||
    String currentContent = widget.emailContent;
 | 
					    String currentContent = widget.emailContent;
 | 
				
			||||||
    viewTypeId = "iframe-${DateTime.now().millisecondsSinceEpoch}";
 | 
					    viewTypeId = "iframe-${DateTime.now().millisecondsSinceEpoch}";
 | 
				
			||||||
    _registerViewFactory(currentContent);
 | 
					    _registerViewFactory(currentContent);
 | 
				
			||||||
 | 
					    _markerPositionsFuture = ApiService().getMarkerPosition(); 
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void _registerViewFactory(String currentContent) {
 | 
					  void _registerViewFactory(String currentContent) {
 | 
				
			||||||
| 
						 | 
					@ -276,7 +394,7 @@ class _EmailViewState extends State<EmailView> {
 | 
				
			||||||
    AugmentClasses.handleJump(spanId);
 | 
					    AugmentClasses.handleJump(spanId);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: void _invisibility(String )
 | 
					  // TODO: void _invisibility(String )  //to make purple numbers not visible
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
| 
						 | 
					@ -285,7 +403,9 @@ class _EmailViewState extends State<EmailView> {
 | 
				
			||||||
        appBar: AppBar(
 | 
					        appBar: AppBar(
 | 
				
			||||||
          title: Text(widget.name),
 | 
					          title: Text(widget.name),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        body: Column(
 | 
					        body: Stack(
 | 
				
			||||||
 | 
					          children: [
 | 
				
			||||||
 | 
					            Column(
 | 
				
			||||||
              children: [
 | 
					              children: [
 | 
				
			||||||
                EmailToolbar(
 | 
					                EmailToolbar(
 | 
				
			||||||
                  onJumpToSpan: _scrollToNumber,
 | 
					                  onJumpToSpan: _scrollToNumber,
 | 
				
			||||||
| 
						 | 
					@ -309,8 +429,7 @@ class _EmailViewState extends State<EmailView> {
 | 
				
			||||||
                  //   print("change");
 | 
					                  //   print("change");
 | 
				
			||||||
                  // widget.emailContent = r"
 | 
					                  // widget.emailContent = r"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// "
 | 
					                  //
 | 
				
			||||||
              // },
 | 
					 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                Row(
 | 
					                Row(
 | 
				
			||||||
                  // title of email
 | 
					                  // title of email
 | 
				
			||||||
| 
						 | 
					@ -355,6 +474,71 @@ class _EmailViewState extends State<EmailView> {
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ],
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Overlay widgets dynamically based on marker positions
 | 
				
			||||||
 | 
					            FutureBuilder<List<Map<String, dynamic>>>(
 | 
				
			||||||
 | 
					              future: _markerPositionsFuture,
 | 
				
			||||||
 | 
					              builder: (context, snapshot) {
 | 
				
			||||||
 | 
					                print("FutureBuilder state: ${snapshot.connectionState}");
 | 
				
			||||||
 | 
					                if (snapshot.connectionState == ConnectionState.waiting) {
 | 
				
			||||||
 | 
					                  return Center(child: CircularProgressIndicator());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (snapshot.hasError) {
 | 
				
			||||||
 | 
					                  print("Error in FutureBuilder: ${snapshot.error}");
 | 
				
			||||||
 | 
					                  return Center(child: Text('error loading markers'));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (snapshot.hasData && snapshot.data != null) {
 | 
				
			||||||
 | 
					                  final markers = snapshot.data!;
 | 
				
			||||||
 | 
					                  return Stack(
 | 
				
			||||||
 | 
					                    children: markers.map((marker) {
 | 
				
			||||||
 | 
					                      return Positioned(
 | 
				
			||||||
 | 
					                        left: marker['x'].toDouble(),
 | 
				
			||||||
 | 
					                        top: marker['y'].toDouble(),
 | 
				
			||||||
 | 
					                        child: GestureDetector(
 | 
				
			||||||
 | 
					                          onTap: () {
 | 
				
			||||||
 | 
					                            print('Tapped on ${marker['id']}');
 | 
				
			||||||
 | 
					                          },
 | 
				
			||||||
 | 
					                          child: Container(
 | 
				
			||||||
 | 
					                            width: 50,
 | 
				
			||||||
 | 
					                            height: 50,
 | 
				
			||||||
 | 
					                            color: Colors.red,
 | 
				
			||||||
 | 
					                            child: Center(
 | 
				
			||||||
 | 
					                              child: Text(
 | 
				
			||||||
 | 
					                                marker['id'],
 | 
				
			||||||
 | 
					                                style: TextStyle(color: Colors.white),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      );
 | 
				
			||||||
 | 
					                    }).toList(),
 | 
				
			||||||
 | 
					                  );
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return SizedBox.shrink(); // No markers found
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            // Red widget overlay
 | 
				
			||||||
 | 
					            // Positioned(
 | 
				
			||||||
 | 
					            //   left: 8, // Adjust based on your desired position
 | 
				
			||||||
 | 
					            //   top: 100 + 44 + 5, // Adjust based on your desired position
 | 
				
			||||||
 | 
					            //   child: IgnorePointer(
 | 
				
			||||||
 | 
					            //     ignoring: true, // Ensures the iframe remains interactive
 | 
				
			||||||
 | 
					            //     child: Container(
 | 
				
			||||||
 | 
					            //       color: Colors.red,
 | 
				
			||||||
 | 
					            //       width: 100,
 | 
				
			||||||
 | 
					            //       height: 50,
 | 
				
			||||||
 | 
					            //       child: Center(
 | 
				
			||||||
 | 
					            //         child: Text(
 | 
				
			||||||
 | 
					            //           'Overlay',
 | 
				
			||||||
 | 
					            //           style: TextStyle(color: Colors.white),
 | 
				
			||||||
 | 
					            //         ),
 | 
				
			||||||
 | 
					            //       ),
 | 
				
			||||||
 | 
					            //     ),
 | 
				
			||||||
 | 
					            //   ),
 | 
				
			||||||
 | 
					            // ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					import 'package:crab_ui/api_service.dart';
 | 
				
			||||||
 | 
					import 'package:crab_ui/structs.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'dart:html' as html;
 | 
					import 'dart:html' as html;
 | 
				
			||||||
import 'dart:js' as js;
 | 
					import 'dart:js' as js;
 | 
				
			||||||
| 
						 | 
					@ -64,8 +66,8 @@ class _DynamicClassesAugment extends State<EmailToolbar> {
 | 
				
			||||||
            child: Text('Reload'),
 | 
					            child: Text('Reload'),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          ElevatedButton(
 | 
					          ElevatedButton(
 | 
				
			||||||
            onPressed: AugmentClasses.handleImages,
 | 
					            onPressed: () => AugmentClasses.handleImages(context),
 | 
				
			||||||
            child: Text('Images'),
 | 
					            child: Text('Attachments'),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          SizedBox(width: 8),
 | 
					          SizedBox(width: 8),
 | 
				
			||||||
          ElevatedButton(
 | 
					          ElevatedButton(
 | 
				
			||||||
| 
						 | 
					@ -206,6 +208,8 @@ class _DynamicClassesAugment extends State<EmailToolbar> {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AugmentClasses {
 | 
					class AugmentClasses {
 | 
				
			||||||
 | 
					  ApiService _apiService = ApiService();
 | 
				
			||||||
 | 
					  static OverlayEntry? _overlayEntry;
 | 
				
			||||||
  static void handleHome(BuildContext context) {
 | 
					  static void handleHome(BuildContext context) {
 | 
				
			||||||
    Navigator.of(context).popUntil((route) => route.isFirst);
 | 
					    Navigator.of(context).popUntil((route) => route.isFirst);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -214,8 +218,85 @@ class AugmentClasses {
 | 
				
			||||||
    print("reload");
 | 
					    print("reload");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static void handleImages() {
 | 
					  static void handleImages(BuildContext context) {
 | 
				
			||||||
    print("Images button pressed");
 | 
					    print("Images button pressed");
 | 
				
			||||||
 | 
					    final overlay = Overlay.of(context);
 | 
				
			||||||
 | 
					    final renderBox = context.findRenderObject() as RenderBox;
 | 
				
			||||||
 | 
					    final offset = renderBox.localToGlobal(Offset.zero);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _overlayEntry = OverlayEntry(
 | 
				
			||||||
 | 
					      builder: (context) => Stack(
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					          // Dimmed background
 | 
				
			||||||
 | 
					          GestureDetector(
 | 
				
			||||||
 | 
					            onTap: () => _overlayEntry?.remove(),
 | 
				
			||||||
 | 
					            child: Container(
 | 
				
			||||||
 | 
					              color: Colors.black54,
 | 
				
			||||||
 | 
					              width: MediaQuery.of(context).size.width,
 | 
				
			||||||
 | 
					              height: MediaQuery.of(context).size.height,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          // Focused content window
 | 
				
			||||||
 | 
					          Center(
 | 
				
			||||||
 | 
					            child: Positioned(
 | 
				
			||||||
 | 
					              left: offset.dx + 500,
 | 
				
			||||||
 | 
					              top: offset.dy + renderBox.size.height + 100,
 | 
				
			||||||
 | 
					              child: Material(
 | 
				
			||||||
 | 
					                elevation: 8,
 | 
				
			||||||
 | 
					                borderRadius: BorderRadius.circular(12),
 | 
				
			||||||
 | 
					                child: ConstrainedBox(
 | 
				
			||||||
 | 
					                  constraints: const BoxConstraints(
 | 
				
			||||||
 | 
					                    maxWidth: 400,
 | 
				
			||||||
 | 
					                    maxHeight: 500,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  child: Column(
 | 
				
			||||||
 | 
					                    children: [
 | 
				
			||||||
 | 
					                      _buildHeader(),
 | 
				
			||||||
 | 
					                      const Divider(height: 1),
 | 
				
			||||||
 | 
					                      Expanded(
 | 
				
			||||||
 | 
					                        child: ListView(
 | 
				
			||||||
 | 
					                          children: _buildMenuItem(),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    if (_overlayEntry != null) {
 | 
				
			||||||
 | 
					      overlay.insert(_overlayEntry!);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Add missing widget builder methods
 | 
				
			||||||
 | 
					  static Widget _buildHeader() {
 | 
				
			||||||
 | 
					    return const Padding(
 | 
				
			||||||
 | 
					      padding: EdgeInsets.all(16.0),
 | 
				
			||||||
 | 
					      child: Text(
 | 
				
			||||||
 | 
					        'Thread Attachments',
 | 
				
			||||||
 | 
					        style: TextStyle(
 | 
				
			||||||
 | 
					          fontSize: 20,
 | 
				
			||||||
 | 
					          fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static List<Widget> _buildMenuItem() {
 | 
				
			||||||
 | 
					    List<Widget> listOfFiles = [];
 | 
				
			||||||
 | 
					    for (AttachmentResponse file in ApiService.threadAttachments) {
 | 
				
			||||||
 | 
					      listOfFiles.add(ListTile(
 | 
				
			||||||
 | 
					          leading: Icon(Icons.file_present),
 | 
				
			||||||
 | 
					          title: Text(file.name.toString()),
 | 
				
			||||||
 | 
					          onTap: () {
 | 
				
			||||||
 | 
					            _overlayEntry?.remove();
 | 
				
			||||||
 | 
					          }));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return listOfFiles;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static void handleOpen() {
 | 
					  static void handleOpen() {
 | 
				
			||||||
| 
						 | 
					@ -517,6 +598,7 @@ class AugmentClasses {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static void disableIframePointerEvents() {
 | 
					  static void disableIframePointerEvents() {
 | 
				
			||||||
 | 
					    //pretty sure these dont work
 | 
				
			||||||
    final iframes = html.document.getElementsByTagName('iframe');
 | 
					    final iframes = html.document.getElementsByTagName('iframe');
 | 
				
			||||||
    for (var iframe in iframes) {
 | 
					    for (var iframe in iframes) {
 | 
				
			||||||
      if (iframe is html.Element) {
 | 
					      if (iframe is html.Element) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,10 +4,12 @@ import 'structs.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EmailListScreen extends StatelessWidget {
 | 
					class EmailListScreen extends StatelessWidget {
 | 
				
			||||||
  final List<GetThreadResponse> emails;
 | 
					  final List<GetThreadResponse> emails;
 | 
				
			||||||
  final Future<String> Function(List<String>) getEmailContent;
 | 
					  final Future<String> Function(List<String>, String) getEmailContent;
 | 
				
			||||||
 | 
					  final String folder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  EmailListScreen({required this.emails, required this.getEmailContent});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  EmailListScreen({required this.emails, required this.getEmailContent, required this.folder});
 | 
				
			||||||
 | 
					//fix the email list
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
| 
						 | 
					@ -24,7 +26,7 @@ class EmailListScreen extends StatelessWidget {
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            trailing: Text(email.date.toString()),
 | 
					            trailing: Text(email.date.toString()),
 | 
				
			||||||
            onTap: () async {
 | 
					            onTap: () async {
 | 
				
			||||||
              String emailContent = await getEmailContent(email.messages);
 | 
					              String emailContent = await getEmailContent(email.messages, folder);
 | 
				
			||||||
              Navigator.push(
 | 
					              Navigator.push(
 | 
				
			||||||
                context,
 | 
					                context,
 | 
				
			||||||
                MaterialPageRoute(
 | 
					                MaterialPageRoute(
 | 
				
			||||||
| 
						 | 
					@ -51,7 +53,7 @@ class EmailListScreen extends StatelessWidget {
 | 
				
			||||||
// ignore: must_be_immutable
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
class EmailPage extends StatefulWidget {
 | 
					class EmailPage extends StatefulWidget {
 | 
				
			||||||
  EmailPage({Key? key}) : super(key: key);
 | 
					  EmailPage({Key? key}) : super(key: key);
 | 
				
			||||||
  String selectedFolder = "INBOX";
 | 
					  String selectedFolder = "INBOX"; //starter
 | 
				
			||||||
  int offset = 0;
 | 
					  int offset = 0;
 | 
				
			||||||
  int page = 1;
 | 
					  int page = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,11 +64,14 @@ class EmailPage extends StatefulWidget {
 | 
				
			||||||
class EmailPageState extends State<EmailPage> {
 | 
					class EmailPageState extends State<EmailPage> {
 | 
				
			||||||
  final ApiService apiService = ApiService();
 | 
					  final ApiService apiService = ApiService();
 | 
				
			||||||
  List<GetThreadResponse> emails = [];
 | 
					  List<GetThreadResponse> emails = [];
 | 
				
			||||||
 | 
					  int page = 1;
 | 
				
			||||||
 | 
					  bool isBackDisabled = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void initState() {
 | 
					  void initState() {
 | 
				
			||||||
    super.initState();
 | 
					    super.initState();
 | 
				
			||||||
    widget.page = widget.page;
 | 
					    widget.page = page;
 | 
				
			||||||
 | 
					    isBackDisabled = true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void updateSelectedFolder(String folder) {
 | 
					  void updateSelectedFolder(String folder) {
 | 
				
			||||||
| 
						 | 
					@ -86,11 +91,16 @@ class EmailPageState extends State<EmailPage> {
 | 
				
			||||||
      setState(() {
 | 
					      setState(() {
 | 
				
			||||||
        widget.offset += 50;
 | 
					        widget.offset += 50;
 | 
				
			||||||
        widget.page += 1;
 | 
					        widget.page += 1;
 | 
				
			||||||
 | 
					        isBackDisabled = false;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    } else if (option == "back") {
 | 
					    } else if (option == "back") {
 | 
				
			||||||
      setState(() {
 | 
					      setState(() {
 | 
				
			||||||
        widget.offset -= 50;
 | 
					        widget.offset -= 50;
 | 
				
			||||||
        widget.page -= 1;
 | 
					        widget.page -= 1;
 | 
				
			||||||
 | 
					        if (widget.page == 1) {
 | 
				
			||||||
 | 
					          isBackDisabled = true;
 | 
				
			||||||
 | 
					          print("back dis");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // print(currentPage);
 | 
					    // print(currentPage);
 | 
				
			||||||
| 
						 | 
					@ -119,6 +129,7 @@ class EmailPageState extends State<EmailPage> {
 | 
				
			||||||
      body: EmailListScreen(
 | 
					      body: EmailListScreen(
 | 
				
			||||||
        emails: emails,
 | 
					        emails: emails,
 | 
				
			||||||
        getEmailContent: apiService.fetchEmailContent,
 | 
					        getEmailContent: apiService.fetchEmailContent,
 | 
				
			||||||
 | 
					        folder: widget.selectedFolder,//try to grab from it directly
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,10 @@
 | 
				
			||||||
import 'package:crab_ui/folder_drawer.dart';
 | 
					import 'folder_drawer.dart';
 | 
				
			||||||
import 'package:crab_ui/structs.dart';
 | 
					import 'structs.dart';
 | 
				
			||||||
import 'package:flutter/widgets.dart';
 | 
					import 'package:flutter/widgets.dart';
 | 
				
			||||||
import 'api_service.dart';
 | 
					import 'api_service.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'email.dart';
 | 
					import 'email.dart';
 | 
				
			||||||
 | 
					// import 'package:shared_preferences/shared_preferences.dart';
 | 
				
			||||||
// import 'serialize.dart';
 | 
					// import 'serialize.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HomeScreen extends StatefulWidget {
 | 
					class HomeScreen extends StatefulWidget {
 | 
				
			||||||
| 
						 | 
					@ -119,7 +120,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
 | 
				
			||||||
            body: ListView.separated(
 | 
					            body: ListView.separated(
 | 
				
			||||||
              itemCount: result.length,
 | 
					              itemCount: result.length,
 | 
				
			||||||
              itemBuilder: (context, index) {
 | 
					              itemBuilder: (context, index) {
 | 
				
			||||||
                final email = result[index];
 | 
					                final SerializableMessage email  = result[index];
 | 
				
			||||||
                return ListTile(
 | 
					                return ListTile(
 | 
				
			||||||
                  title: Text(email.from,
 | 
					                  title: Text(email.from,
 | 
				
			||||||
                      style: TextStyle(fontWeight: FontWeight.bold)),
 | 
					                      style: TextStyle(fontWeight: FontWeight.bold)),
 | 
				
			||||||
| 
						 | 
					@ -131,7 +132,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
 | 
				
			||||||
                  onTap: () async {
 | 
					                  onTap: () async {
 | 
				
			||||||
                    // print('tapped');
 | 
					                    // print('tapped');
 | 
				
			||||||
                    String emailContent =
 | 
					                    String emailContent =
 | 
				
			||||||
                        await apiService.fetchEmailContent([email.id]);
 | 
					                        await apiService.fetchEmailContent([email.id], email.list);
 | 
				
			||||||
                    // print('content below');
 | 
					                    // print('content below');
 | 
				
			||||||
                    // print(emailContent);
 | 
					                    // print(emailContent);
 | 
				
			||||||
                    Navigator.push(
 | 
					                    Navigator.push(
 | 
				
			||||||
| 
						 | 
					@ -341,7 +342,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
 | 
				
			||||||
                        children: [
 | 
					                        children: [
 | 
				
			||||||
                          ElevatedButton(
 | 
					                          ElevatedButton(
 | 
				
			||||||
                            onPressed: () {
 | 
					                            onPressed: () {
 | 
				
			||||||
                              _emailPageKey.currentState
 | 
					                              _emailPageKey.currentState!.isBackDisabled ? null: _emailPageKey.currentState
 | 
				
			||||||
                                  ?.updatePagenation('back');
 | 
					                                  ?.updatePagenation('back');
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
                            child: Icon(Icons.navigate_before),
 | 
					                            child: Icon(Icons.navigate_before),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ dependencies:
 | 
				
			||||||
  encrypt: ^5.0.0
 | 
					  encrypt: ^5.0.0
 | 
				
			||||||
  pointycastle: ^3.4.0
 | 
					  pointycastle: ^3.4.0
 | 
				
			||||||
  mime: ^1.0.3
 | 
					  mime: ^1.0.3
 | 
				
			||||||
 | 
					  pointer_interceptor: ^0.10.1+2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  english_words: ^4.0.0
 | 
					  english_words: ^4.0.0
 | 
				
			||||||
  provider: ^6.0.0
 | 
					  provider: ^6.0.0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue