scrapped html package and js, now using web

This commit is contained in:
Juan Marulanda De Los Rios 2025-05-14 21:52:21 -04:00
parent 7a1e735f11
commit 9fff611ac0
3 changed files with 167 additions and 145 deletions

View File

@ -12,8 +12,10 @@ 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; // import 'dart:js' as js;
import 'package:web/web.dart' as web;
import 'dart:js_interop' as js;
class ApiService { class ApiService {
static String ip = ""; static String ip = "";
@ -343,76 +345,77 @@ class ApiService {
return AttachmentResponse(name: "error", data: Uint8List(0)); return AttachmentResponse(name: "error", data: Uint8List(0));
} }
Future<List<Map<String, dynamic>>> getMarkerPosition() async { //TODO: MOVE THIS INTO WEB
//this is so we can put a widget right below each email, but the way how the email content is generated // Future<List<Map<String, dynamic>>> getMarkerPosition() async {
//leads to problems as for a) the html is added one right after the other in one iframe, b) // //this is so we can put a widget right below each email, but the way how the email content is generated
// if it was multiple iframes then the scrolling to jump would not work as expected // //leads to problems as for a) the html is added one right after the other in one iframe, b)
// // if it was multiple iframes then the scrolling to jump would not work as expected
print("marker called"); // print("marker called");
// JavaScript code embedded as a string // // JavaScript code embedded as a string
String jsCode = ''' // String jsCode = '''
(async function waitForIframeAndMarkers() { // (async function waitForIframeAndMarkers() {
try { // try {
return await new Promise((resolve) => { // return await new Promise((resolve) => {
const interval = setInterval(() => { // const interval = setInterval(() => {
console.log("⏳ Checking for iframe..."); // console.log("⏳ Checking for iframe...");
var iframe = document.getElementsByTagName('iframe')[0]; // var iframe = document.getElementsByTagName('iframe')[0];
if (iframe && iframe.contentDocument) { // if (iframe && iframe.contentDocument) {
console.log("✅ Iframe found!"); // console.log("✅ Iframe found!");
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document; // var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
var markers = iframeDoc.querySelectorAll('[id^="JuanBedarramarker"]'); // var markers = iframeDoc.querySelectorAll('[id^="JuanBedarramarker"]');
if (markers.length > 0) { // if (markers.length > 0) {
console.log(` Found markers in the iframe.`); // console.log(` Found markers in the iframe.`);
var positions = []; // var positions = [];
markers.forEach((marker) => { // markers.forEach((marker) => {
var rect = marker.getBoundingClientRect(); // var rect = marker.getBoundingClientRect();
positions.push({ // positions.push({
id: marker.id, // id: marker.id,
x: rect.left + window.scrollX, // x: rect.left + window.scrollX,
y: rect.top + window.scrollY, // y: rect.top + window.scrollY,
}); // });
}); // });
console.log("📌 Marker positions:", positions); // console.log("📌 Marker positions:", positions);
clearInterval(interval); // clearInterval(interval);
resolve(JSON.stringify(positions)); // Ensure proper JSON string // resolve(JSON.stringify(positions)); // Ensure proper JSON string
} else { // } else {
console.log("❌ No markers found yet."); // console.log("❌ No markers found yet.");
} // }
} else { // } else {
console.log("❌ Iframe not found or not loaded yet."); // console.log("❌ Iframe not found or not loaded yet.");
} // }
}, 200); // }, 200);
}); // });
} catch (error) { // } catch (error) {
console.error("JS Error:", error); // console.error("JS Error:", error);
throw error; // Propagate error to Dart // throw error; // Propagate error to Dart
} // }
})(); // })();
'''; // ''';
try { // try {
// Execute the JavaScript code using eval // // Execute the JavaScript code using eval
final result = await js.context.callMethod('eval', [jsCode]); // // final result = await js.context.callMethod('eval', [jsCode]);
if (result != null && result is String) { // if (result != null && result is String) {
print("Result received: $result"); // print("Result received: $result");
// Parse the JSON string returned by JavaScript into a Dart list of maps // // Parse the JSON string returned by JavaScript into a Dart list of maps
final List<dynamic> parsedResult = jsonDecode(result); // final List<dynamic> parsedResult = jsonDecode(result);
var positions = List<Map<String, dynamic>>.from(parsedResult); // var positions = List<Map<String, dynamic>>.from(parsedResult);
print("positions put on"); // print("positions put on");
print(positions); // print(positions);
return positions; // return positions;
} else { // } else {
print("result is null or not a string"); // print("result is null or not a string");
} // }
} catch (e, stackTrace) { // } catch (e, stackTrace) {
print("Error executing JavaScript: $e"); // print("Error executing JavaScript: $e");
print(stackTrace); // print(stackTrace);
} // }
return []; // return [];
} // }
} }
class EmailView extends StatefulWidget { class EmailView extends StatefulWidget {
@ -455,10 +458,12 @@ class _EmailViewState extends State<EmailView> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
String currentContent = widget.emailContent; String currentContent = widget
.emailContent; //html of the email/ actually entire thread, gives me little space to play in between
// i wonder if the other attributes change? because if so i have to add like some zooms in and out of the emails, as in collapse
viewTypeId = "iframe-${DateTime.now().millisecondsSinceEpoch}"; viewTypeId = "iframe-${DateTime.now().millisecondsSinceEpoch}";
_registerViewFactory(currentContent); _registerViewFactory(currentContent);
_markerPositionsFuture = ApiService().getMarkerPosition(); // _markerPositionsFuture = ApiService().getMarkerPosition();
} }
void _registerViewFactory(String currentContent) { void _registerViewFactory(String currentContent) {
@ -466,11 +471,20 @@ class _EmailViewState extends State<EmailView> {
viewTypeId = 'iframe-${DateTime.now().millisecondsSinceEpoch}'; viewTypeId = 'iframe-${DateTime.now().millisecondsSinceEpoch}';
ui.platformViewRegistry.registerViewFactory( ui.platformViewRegistry.registerViewFactory(
viewTypeId, viewTypeId,
(int viewId) => html.IFrameElement() (int viewId) => web.HTMLDivElement()
..width = '100%' ..id = 'new-web'
..height = '100%' ..innerHTML = currentContent as js.JSAny);
..srcdoc = currentContent
..style.border = 'none'); // DivElement div = HTMLDivElement()
// ..id =
// ui.platformViewRegistry.registerViewFactory(
// viewTypeId,
// (int viewId) => html.IFrameElement()
// ..width = '100%'
// ..height = '100%'
// ..srcdoc = currentContent
// ..style.border = 'none');
}); });
} }
@ -502,7 +516,7 @@ class _EmailViewState extends State<EmailView> {
// <h1>Welcome to My Website</h1> // <h1>Welcome to My Website</h1>
// <p>This is a simple HTML page.</p> // <p>This is a simple HTML page.</p>
// <h2>What is HTML?</h2> // <h2>What is HTML?</h2>
// <p>HTML (HyperText Markup Language) is the most basic building block of the Web. It defines the meaning and structure of web content. Other technologies besides HTML are generally used to describe a web page's appearance/presentation (CSS) or functionality/behavior (JavaScript).</p> // <p>HTML (HyperText Markup Language) is the most basic building~ block of the Web. It defines the meaning and structure of web content. Other technologies besides HTML are generally used to describe a web page's appearance/presentation (CSS) or functionality/behavior (JavaScript).</p>
// <h3>Here's a simple list:</h3> // <h3>Here's a simple list:</h3>
// <ul> // <ul>
// <li>HTML elements are the building blocks of HTML pages</li> // <li>HTML elements are the building blocks of HTML pages</li>
@ -562,48 +576,48 @@ class _EmailViewState extends State<EmailView> {
), ),
// Overlay widgets dynamically based on marker positions // Overlay widgets dynamically based on marker positions
FutureBuilder<List<Map<String, dynamic>>>( // FutureBuilder<List<Map<String, dynamic>>>(
future: _markerPositionsFuture, // future: _markerPositionsFuture,
builder: (context, snapshot) { // builder: (context, snapshot) {
print("FutureBuilder state: ${snapshot.connectionState}"); // print("FutureBuilder state: ${snapshot.connectionState}");
if (snapshot.connectionState == ConnectionState.waiting) { // if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator()); // return Center(child: CircularProgressIndicator());
} // }
if (snapshot.hasError) { // if (snapshot.hasError) {
print("Error in FutureBuilder: ${snapshot.error}"); // print("Error in FutureBuilder: ${snapshot.error}");
return Center(child: Text('error loading markers')); // return Center(child: Text('error loading markers'));
} // }
if (snapshot.hasData && snapshot.data != null) { // if (snapshot.hasData && snapshot.data != null) {
final markers = snapshot.data!; // final markers = snapshot.data!;
return Stack( // return Stack(
children: markers.map((marker) { // children: markers.map((marker) {
return Positioned( // return Positioned(
left: marker['x'].toDouble(), // left: marker['x'].toDouble(),
top: marker['y'].toDouble(), // top: marker['y'].toDouble(),
child: GestureDetector( // child: GestureDetector(
onTap: () { // onTap: () {
print('Tapped on ${marker['id']}'); // print('Tapped on ${marker['id']}');
}, // },
child: Container( // child: Container(
width: 50, // width: 50,
height: 50, // height: 50,
color: Colors.red, // color: Colors.red,
child: Center( // child: Center(
child: Text( // child: Text(
marker['id'], // marker['id'],
style: TextStyle(color: Colors.white), // style: TextStyle(color: Colors.white),
), // ),
), // ),
), // ),
), // ),
); // );
}).toList(), // }).toList(),
); // );
} // }
return SizedBox.shrink(); // No markers found // return SizedBox.shrink(); // No markers found
}, // },
), // ),
// Red widget overlay // Red widget overlay
// Positioned( // Positioned(
// left: 8, // Adjust based on your desired position // left: 8, // Adjust based on your desired position

View File

@ -1,4 +1,5 @@
import 'dart:html' as html; import 'dart:html' as html;
import 'package:web/web.dart' as web;
import 'dart:io'; import 'dart:io';
import 'structs.dart'; import 'structs.dart';
import 'package:file_saver/file_saver.dart'; import 'package:file_saver/file_saver.dart';

View File

@ -6,8 +6,9 @@ import 'package:crab_ui/structs.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pdfrx/pdfrx.dart'; import 'package:pdfrx/pdfrx.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'dart:html' as html; // import 'dart:html' as html;
import 'dart:js' as js; // import 'dart:js' as js;
import 'package:web/web.dart' as web;
import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'attachmentWidget.dart'; import 'attachmentWidget.dart';
@ -326,7 +327,8 @@ class AugmentClasses {
groupValue: selectedFolder, groupValue: selectedFolder,
onChanged: (String? value) { onChanged: (String? value) {
setState(() { setState(() {
selectedFolder = value; // Update the selected folder selectedFolder =
value; // Update the selected folder
}); });
}, },
); );
@ -352,8 +354,8 @@ class AugmentClasses {
print("Selected folder: $selectedFolder"); print("Selected folder: $selectedFolder");
// Store the selected folder or perform any action // Store the selected folder or perform any action
// ApiService.currFolder = selectedFolder!; // ApiService.currFolder = selectedFolder!;
ApiService() ApiService().moveEmail(ApiService.currFolder,
.moveEmail(ApiService.currFolder, ApiService.currThreadID, selectedFolder!); ApiService.currThreadID, selectedFolder!);
_overlayEntry?.remove(); _overlayEntry?.remove();
} else { } else {
print("No folder selected"); print("No folder selected");
@ -512,7 +514,7 @@ class AugmentClasses {
console.log('Iframe not found or not loaded.'); console.log('Iframe not found or not loaded.');
} }
'''; ''';
js.context.callMethod('eval', [js_code]); // js.context.callMethod('eval', [js_code]);
} }
static void invisibility(String htmlClass) {} static void invisibility(String htmlClass) {}
@ -520,7 +522,7 @@ class AugmentClasses {
static Future<void> JumpButton(BuildContext context) async { static Future<void> JumpButton(BuildContext context) async {
// FocusNode textFieldFocusNode = FocusNode(); // FocusNode textFieldFocusNode = FocusNode();
AugmentClasses.disableIframePointerEvents(); // AugmentClasses.disableIframePointerEvents();
await showDialog( await showDialog(
barrierDismissible: true, barrierDismissible: true,
// barrierColor: Colors.yellow, // barrierColor: Colors.yellow,
@ -602,7 +604,7 @@ class AugmentClasses {
], ],
), ),
).then((_) { ).then((_) {
AugmentClasses.enableIframePointerEvents(); // AugmentClasses.enableIframePointerEvents();
}); });
} }
@ -612,7 +614,7 @@ class AugmentClasses {
bool blankLines = false; bool blankLines = false;
bool numbering = false; bool numbering = false;
bool statementSignatures = false; bool statementSignatures = false;
AugmentClasses.disableIframePointerEvents(); // AugmentClasses.disableIframePointerEvents();
await showDialog( await showDialog(
context: context, context: context,
builder: (context) => Container( builder: (context) => Container(
@ -723,7 +725,7 @@ class AugmentClasses {
ElevatedButton(onPressed: () {}, child: Text('OK')), ElevatedButton(onPressed: () {}, child: Text('OK')),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
AugmentClasses.disableIframePointerEvents(); // AugmentClasses.disableIframePointerEvents();
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
child: Text('Cancel')), child: Text('Cancel')),
@ -737,7 +739,7 @@ class AugmentClasses {
), ),
), ),
)).then((_) { )).then((_) {
AugmentClasses.enableIframePointerEvents(); // may be useless? // AugmentClasses.enableIframePointerEvents(); // may be useless?
}); });
} }
@ -747,7 +749,7 @@ class AugmentClasses {
//idea is to search in file, extract the <p> tags that contain these //idea is to search in file, extract the <p> tags that contain these
//words and highlight, then when zoom, you just jump to that paragraph //words and highlight, then when zoom, you just jump to that paragraph
AugmentClasses.disableIframePointerEvents(); // AugmentClasses.disableIframePointerEvents();
await showDialog( await showDialog(
context: context, context: context,
builder: (context) => Container( builder: (context) => Container(
@ -775,22 +777,27 @@ class AugmentClasses {
))))); )))));
} }
static void disableIframePointerEvents() { // static void disableIframePointerEvents() {
//pretty sure these dont work // //pretty sure these dont work
final iframes = html.document.getElementsByTagName('iframe'); // // final iframes = html.document.getElementsByTagName('iframe');
for (var iframe in iframes) { // final iframes = web.document.getElementsByTagName('iframe');
if (iframe is html.Element) { // for (var iframe in iframes) {
iframe.style.pointerEvents = 'none'; // Disable pointer events // // if (iframe is html.Element) {
} // // iframe.style.pointerEvents = 'none'; // Disable pointer events
} // if (iframe is web.Element) {
} // iframe.
// }
// }
// }
static void enableIframePointerEvents() { // static void enableIframePointerEvents() {
final iframes = html.document.getElementsByTagName('iframe'); // // final iframes = html.document.getElementsByTagName('iframe');
for (var iframe in iframes) { // final iframes = html.document.getElementsByTagName('iframe');
if (iframe is html.Element) {
iframe.style.pointerEvents = 'auto'; // Re-enable pointer events // for (var iframe in iframes) {
} // if (iframe is html.Element) {
} // iframe.style.pointerEvents = 'auto'; // Re-enable pointer events
} // }
// }
// }
} }