hym_ui/lib/collapsableEmailsWeb.dart

256 lines
8.8 KiB
Dart

import 'dart:js_interop';
import 'dart:js_interop_unsafe';
import 'package:web/web.dart' as web;
import 'package:flutter/material.dart';
import 'dart:ui_web' as ui;
import 'api_service.dart';
import 'structs.dart';
class CollapsableEmails extends StatefulWidget {
final List<String> thread; // email id's in the form xyz@gmail.com
final List<String> threadHTML;
final String threadIDs;
CollapsableEmails(
{required this.thread,
required this.threadHTML,
required this.threadIDs});
@override
State<CollapsableEmails> createState() => _CollapsableEmailsState();
}
class _CollapsableEmailsState extends State<CollapsableEmails> {
List<String> emailsHTML = []; //html of the emails in the thread
// build attachments with the forldar name and id
Set<int> _expandedEmails = {}; //open emails
List viewtypeIDs = []; //IDs of the viewtypes, order matters
List heightOfViewTypes = []; //the height of each viewtype
List<SerializableMessage> emailsInThread = [];
bool _isLoaded = false;
static bool _isListenerRegistered = false;
static bool left = true;
static bool right = true;
web.EventListener? _listener;
List<String> hirarchy = ["h1", "h2", "h3", "h4", "h5", "h6", "p"];
List<String> tagsCollected = [];
@override
void initState() {
super.initState();
_registerViewFactory(widget.threadHTML);
_serializableData(widget.threadIDs); // this
_keyListener();
}
// @override
// void dispose() {
// if (_listener != null) {
// web.window.document.removeEventListener('keydown', _listener!);
// }
// super.dispose();
// }
void _registerViewFactory(List<String> currentContent) async {
// setState(() { //update to do item per item
// each item to have itsviewtype ID
// is this necessarey here??
//could just move to collapsable
for (var emailHTML in widget.threadHTML) {
String viewTypeId = 'email-${DateTime.now().millisecondsSinceEpoch}';
final ghost = web.document.createElement('div') as web.HTMLDivElement
..style.visibility = 'hidden'
..style.position = 'absolute'
..style.width = '100%'
..style.overflow = 'auto'
..innerHTML = emailHTML
.toJS; // temporarily index because it has to do all of them
web.document.body?.append(ghost);
await Future.delayed(Duration(milliseconds: 10));
final heightOfEmail = ghost.scrollHeight;
ghost.remove();
final HTMLsnippet = web.document.createElement('div')
as web.HTMLDivElement
..id = viewTypeId
..innerHTML = emailHTML
.toJS; // temporarily index because it has to do all of them
HTMLsnippet.style
..width = '100%'
..height = '${heightOfEmail}px'
..overflow = 'auto'
..scrollBehavior = 'smooth';
ui.platformViewRegistry.registerViewFactory(
viewTypeId,
(int viewId) => HTMLsnippet,
);
viewtypeIDs.add(viewTypeId);
heightOfViewTypes.add(heightOfEmail);
}
}
void _serializableData(String threadID) async {
emailsInThread = await ApiService().threadsInSerializable(threadID);
print("done thread serializable");
if (!mounted) return;
setState(() {
_isLoaded = true;
});
}
void handleKeyDown(web.Event event) {
final keyEvent = event as web.KeyboardEvent;
if (keyEvent.key == 'G') {
print('You pressed the "G" key!');
final rightPurpleNums = web.document.getElementsByClassName("right");
_CollapsableEmailsState.right = !_CollapsableEmailsState.right;
final newOpacity = _CollapsableEmailsState.right ? '1.0' : '0.0';
for (int i = 0; i < rightPurpleNums.length; i++) {
final currentElement = rightPurpleNums.item(i) as web.HTMLElement;
currentElement.style.opacity = newOpacity;
}
} else if (keyEvent.key == 'H') {
print('You pressed the "H" key!');
final leftPurpleNums = web.document.getElementsByClassName("left");
_CollapsableEmailsState.left = !_CollapsableEmailsState.left;
final newOpacity = _CollapsableEmailsState.left ? '1.0' : '0.0';
for (int i = 0; i < leftPurpleNums.length; i++) {
final currentElement = leftPurpleNums.item(i) as web.HTMLElement;
currentElement.style.opacity = newOpacity;
}
} else if (keyEvent.key == 'm') {
print("you pressed 'm'");
final purpleNums = web.document.getElementsByClassName("purplenumber");
_CollapsableEmailsState.left = true;
_CollapsableEmailsState.right = true;
for (int i = 0; i < purpleNums.length; i++) {
final currentElement = purpleNums.item(i) as web.HTMLElement;
currentElement.style.opacity = '1.0';
}
} else if (keyEvent.key == 'n') {
print("you pressed 'n'");
final purpleNums = web.document.getElementsByClassName("purplenumber");
_CollapsableEmailsState.left = false;
_CollapsableEmailsState.right = false;
for (int i = 0; i < purpleNums.length; i++) {
final currentElement = purpleNums.item(i) as web.HTMLElement;
currentElement.style.opacity = '0.0';
}
} else if (keyEvent.key == 'w') {
print("you pressed 'w'");
getTopLevel();
}
}
void _keyListener() {
if (_isListenerRegistered) return;
_isListenerRegistered = true;
// Convert the top-level function to JS-compatible
_listener = handleKeyDown.toJS;
web.window.document.addEventListener('keydown', _listener!);
}
void getTopLevel() {
print("started top");
int highest = 0;
AugmentTree zoomTreeRoot = AugmentTree();
// zoomTreeRoot.data = emailsHTML[0]; // whole thing
while (highest < hirarchy.length - 1) {
var highestElement = web.document.querySelectorAll(hirarchy[highest]);
print("nodelist $highestElement");
if (highestElement.isNull || highestElement.length == 0) {
//from h1, h2, h3, ..., p.
highest += 1;
print(hirarchy[highest]);
} else {
AugmentTree newLevel = AugmentTree(); // list of children of each level
for (int i = 0; i < highestElement.length; i++) {
print(highestElement.item(i)?.textContent);
tagsCollected
.add(highestElement.item(i)?.textContent ?? "nameless subtitle");
newLevel.children
.add(highestElement.item(i)?.textContent ?? "nameless subtitle");
}
// traverse to last node and add new level to it
// next
if (zoomTreeRoot.node == null) {
zoomTreeRoot.node = newLevel;
} else {
AugmentTree temp = zoomTreeRoot;
while (true) {
//get to the last and assign node = last node
if (temp.node != null) {
temp = temp.node!;
} else {
temp.node = newLevel;
break;
}
}
}
highest += 1;
}
}
print("out safely");
print(tagsCollected); //instead of a list make a tree
print(zoomTreeRoot.children);
print(zoomTreeRoot.node?.children);
print(zoomTreeRoot.node?.node?.children);
print(zoomTreeRoot.node?.node?.node?.children);
}
@override
Widget build(BuildContext context) {
return _isLoaded
? Column(children: [
Expanded(
child: ListView.builder(
itemCount: widget.thread.length,
itemBuilder: (context, index) {
final isExpanded = _expandedEmails
.contains(index); //check if email is expanded
return Column(
children: [
ListTile(
title: Text(emailsInThread[index].from),
trailing: Text(emailsInThread[index].date),
onTap: () {
setState(() {
if (isExpanded) {
_expandedEmails.remove(index);
} else {
_expandedEmails.add(index);
}
});
},
),
if (isExpanded)
SizedBox(
height: heightOfViewTypes[index].toDouble(),
child: HtmlElementView(
key: UniqueKey(), viewType: viewtypeIDs[index]),
),
Divider(),
],
);
},
),
)
])
: const Center(child: CircularProgressIndicator());
}
}