data structure works
This commit is contained in:
parent
df63293977
commit
a1fde46aec
@ -1,3 +1,4 @@
|
||||
import 'dart:collection';
|
||||
import 'dart:js_interop';
|
||||
import 'dart:js_interop_unsafe';
|
||||
import 'package:web/web.dart' as web;
|
||||
@ -5,6 +6,9 @@ import 'package:flutter/material.dart';
|
||||
import 'dart:ui_web' as ui;
|
||||
import 'api_service.dart';
|
||||
import 'structs.dart';
|
||||
import 'package:html2md/html2md.dart' as html2md;
|
||||
import 'package:markdown_widget/markdown_widget.dart';
|
||||
import 'package:markdown/markdown.dart' as md;
|
||||
|
||||
class CollapsableEmails extends StatefulWidget {
|
||||
final List<String> thread; // email id's in the form xyz@gmail.com
|
||||
@ -33,22 +37,234 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
|
||||
static bool right = true;
|
||||
web.EventListener? _listener;
|
||||
List<String> hirarchy = ["h1", "h2", "h3", "h4", "h5", "h6", "p"];
|
||||
Map<String, int> hirarchyDict = {
|
||||
"h1": 1,
|
||||
"h2": 2,
|
||||
"h3": 3,
|
||||
"h4": 4,
|
||||
"h5": 6,
|
||||
"h6": 7,
|
||||
"p": 8,
|
||||
"ul": 8,
|
||||
"li": 8,
|
||||
};
|
||||
|
||||
List<String> tagsCollected = [];
|
||||
String markdown = '';
|
||||
List<List<String>> sentinel = [];
|
||||
int level = 0;
|
||||
AugmentTree root = AugmentTree();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_registerViewFactory(widget.threadHTML);
|
||||
_serializableData(widget.threadIDs); // this
|
||||
_markdownConverter();
|
||||
// _registerViewFactory(widget.threadHTML);
|
||||
// _serializableData(widget.threadIDs); // this
|
||||
_markdown2Tree(markdown);
|
||||
_keyListener();
|
||||
_buildForZooms(level);
|
||||
}
|
||||
// @override
|
||||
// void dispose() {
|
||||
// if (_listener != null) {
|
||||
// web.window.document.removeEventListener('keydown', _listener!);
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_listener != null) {
|
||||
web.window.document.removeEventListener('keydown', _listener!);
|
||||
_listener = null;
|
||||
_isListenerRegistered = false;
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _markdownConverter() async {
|
||||
markdown = html2md.convert(widget.threadHTML[0]);
|
||||
}
|
||||
|
||||
void _add2Tree(AugmentTree tree, md.Element node2add) {
|
||||
// adds node to its corresponding place
|
||||
AugmentTree newNode = AugmentTree();
|
||||
newNode.setData(node2add.textContent);
|
||||
newNode.ogTag = node2add.tag;
|
||||
// cases,
|
||||
//1. a node that comes is lower than the root.children last, if so it goes beneath it
|
||||
if (tree.children.isEmpty) {
|
||||
// new level to be created when totally empty
|
||||
print('is empty');
|
||||
tree.children.add(newNode);
|
||||
newNode.parent = tree;
|
||||
} else if (tree.children.isNotEmpty &&
|
||||
tree.children.last.ogTag.isNotEmpty) {
|
||||
if ((hirarchyDict[node2add.tag] ??
|
||||
-1) < // e.g. new node is h1 and old is h2, heapify
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1)) {
|
||||
//have to figure out the borthers
|
||||
//assuming it all goes right
|
||||
if ((hirarchyDict[node2add.tag] ?? -1) == -1 ||
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1) == -1) {
|
||||
print(
|
||||
'failed and got -1 at _add2Tree \n ${hirarchyDict[node2add.tag] ?? -1} < ${hirarchyDict[tree.children.last.ogTag] ?? -1}');
|
||||
return;
|
||||
} else if (tree.children.last.parent == null) {
|
||||
// becomes the new top level
|
||||
for (AugmentTree brother in tree.children) {
|
||||
brother.parent = newNode;
|
||||
}
|
||||
tree.children = [newNode];
|
||||
} else {
|
||||
tree.children.add(newNode);
|
||||
}
|
||||
// } else{ // so the node should go high
|
||||
// _add2Tree(tree.children.last, node2add);
|
||||
// }
|
||||
// super.dispose();
|
||||
|
||||
//maybe?
|
||||
// } else {
|
||||
// }
|
||||
} else if ((hirarchyDict[node2add.tag] ??
|
||||
-1) > // go down e.g. new node is h3 and old is h2 or something
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1)) {
|
||||
if ((hirarchyDict[node2add.tag] ?? -1) == -1 ||
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1) == -1) {
|
||||
print(
|
||||
'failed and got -1 at _add2Tree \n ${hirarchyDict[node2add.tag] ?? -1} > ${hirarchyDict[tree.children.last.ogTag] ?? -1}');
|
||||
print("-1 ${tree.children.last.ogTag}");
|
||||
return;
|
||||
}
|
||||
|
||||
print("> ${node2add.tag}");
|
||||
|
||||
_add2Tree(tree.children.last, node2add);
|
||||
} else if ((hirarchyDict[node2add.tag] ?? -1) ==
|
||||
(hirarchyDict[tree.children.last.ogTag] ?? -1)) {
|
||||
print("equals??");
|
||||
tree.children.add(newNode);
|
||||
newNode.parent = tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _markdown2Tree(String text) {
|
||||
print("started markdown2tree");
|
||||
int highest = 0;
|
||||
AugmentTree zoomTreeRoot = AugmentTree();
|
||||
final List<md.Node> nakedList = md.Document().parseLines(text.split('\n'));
|
||||
List<String> pList = [];
|
||||
List<String> h1List = [];
|
||||
List<String> h2List = [];
|
||||
List<String> h3List = [];
|
||||
List<String> h4List = [];
|
||||
List<String> h5List = [];
|
||||
List<String> h6List = [];
|
||||
|
||||
for (var node in nakedList) {
|
||||
//maybe do an add function, but isn't this it?
|
||||
if (node is md.Element) {
|
||||
// print(node.textContent);
|
||||
AugmentTree temp = AugmentTree();
|
||||
temp.data = node.textContent;
|
||||
temp.ogTag = node.tag;
|
||||
if (node.tag == 'h1') {
|
||||
h1List.add(node.textContent);
|
||||
_add2Tree(zoomTreeRoot, node);
|
||||
} else if (node.tag == 'h2') {
|
||||
// i dont add any since i dont have it, maybe the function makes sense
|
||||
h2List.add(node.textContent);
|
||||
} else if (node.tag == 'h3') {
|
||||
h3List.add(node.textContent);
|
||||
root.children.add(temp);
|
||||
_add2Tree(zoomTreeRoot, node);
|
||||
} else if (node.tag == 'h4') {
|
||||
h4List.add(node.textContent); //this broke it
|
||||
_add2Tree(zoomTreeRoot, node); // change to temp
|
||||
if (root.children.isNotEmpty) {
|
||||
root.children.last.children.add(temp);
|
||||
}
|
||||
} else if (node.tag == 'h5') {
|
||||
h5List.add(node.textContent);
|
||||
print(node.textContent);
|
||||
_add2Tree(zoomTreeRoot, node);
|
||||
if (root.children.last.children.isNotEmpty) {
|
||||
print("h5 index ${root.children.last.children.length}");
|
||||
root.children.last.children.last.children.add(temp);
|
||||
print(
|
||||
"h5 after index length ${root.children.last.children.last.children.length}");
|
||||
}
|
||||
} else if (node.tag == 'h6') {
|
||||
h6List.add(node.textContent);
|
||||
if (root.children.last.children.isNotEmpty) {
|
||||
print(
|
||||
"h6 index ${root.children.last.children.last.children.length}");
|
||||
root.children.last.children.last.children.add(temp);
|
||||
print(node.textContent);
|
||||
_add2Tree(zoomTreeRoot, node);
|
||||
}
|
||||
// root.children.last.children.last.children.add(temp);
|
||||
} else if (node.tag == 'p' || node.tag == 'ul' || node.tag == 'li') {
|
||||
pList.add(node.textContent);
|
||||
_add2Tree(zoomTreeRoot, node); // fix this
|
||||
|
||||
if (root.children.isEmpty) {
|
||||
root.children.add(temp);
|
||||
} else if (root.children.last.children.isNotEmpty) {
|
||||
//perhaps recursive
|
||||
root.children.last.children.last.children.add(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.sentinel = [h1List, h2List, h3List, h4List, h5List, h6List, pList];
|
||||
sentinel.removeWhere((hList) => hList.isEmpty);
|
||||
|
||||
print('algorithm adding: ');
|
||||
print("first layer: ${zoomTreeRoot.children}");
|
||||
print("first node: ${zoomTreeRoot.children[0].data}"); //good
|
||||
print("second layer: ${zoomTreeRoot.children.last.children}"); //good
|
||||
print(
|
||||
"first node: ${zoomTreeRoot.children.last.children.first.data}"); //good
|
||||
for (int n = 1; n < zoomTreeRoot.children.last.children.length - 1; n++) {
|
||||
//good
|
||||
print(zoomTreeRoot.children.last.children[n].data);
|
||||
}
|
||||
print("last node: ${zoomTreeRoot.children.last.children.last.data}"); //good
|
||||
print("third layer");
|
||||
for (int thirdLayer = 0;
|
||||
thirdLayer < zoomTreeRoot.children.last.children.length;
|
||||
thirdLayer++) {
|
||||
print(zoomTreeRoot.children.last.children[thirdLayer].children);
|
||||
}
|
||||
print("third layer contents first"); //not sure
|
||||
|
||||
print(zoomTreeRoot.children.last.children[5].children[0].data); //good
|
||||
for (int contentsOf4 = 1;
|
||||
contentsOf4 < zoomTreeRoot.children.last.children[5].children.length;
|
||||
contentsOf4++) {
|
||||
print(zoomTreeRoot.children.last.children[5].children[contentsOf4].data);
|
||||
}
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_isLoaded = true;
|
||||
});
|
||||
}
|
||||
|
||||
void handleKeyDownMD(web.Event event) async {
|
||||
final keyEvent = event as web.KeyboardEvent;
|
||||
|
||||
if (!mounted) return;
|
||||
if (keyEvent.key == 'a') {
|
||||
print("key a");
|
||||
setState(() {
|
||||
level = (level - 1).clamp(0, sentinel.length - 1);
|
||||
});
|
||||
// _buildForZooms(level + 1); //probably need a level?
|
||||
} else if (keyEvent.key == "b") {
|
||||
print("b");
|
||||
setState(() {
|
||||
level = (level + 1).clamp(0, sentinel.length - 1);
|
||||
});
|
||||
// _buildForZooms(level - 1); //probably need a level?
|
||||
}
|
||||
}
|
||||
|
||||
void _registerViewFactory(List<String> currentContent) async {
|
||||
// setState(() { //update to do item per item
|
||||
@ -102,7 +318,7 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
|
||||
});
|
||||
}
|
||||
|
||||
void handleKeyDown(web.Event event) {
|
||||
void handleKeyDownHTML(web.Event event) {
|
||||
final keyEvent = event as web.KeyboardEvent;
|
||||
|
||||
if (keyEvent.key == 'G') {
|
||||
@ -145,7 +361,7 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
|
||||
}
|
||||
} else if (keyEvent.key == 'w') {
|
||||
print("you pressed 'w'");
|
||||
getTopLevel();
|
||||
// getTopLevel();
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,62 +370,91 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
|
||||
_isListenerRegistered = true;
|
||||
|
||||
// Convert the top-level function to JS-compatible
|
||||
_listener = handleKeyDown.toJS;
|
||||
// _listener = handleKeyDownHTML.toJS;
|
||||
_listener = handleKeyDownMD.toJS;
|
||||
|
||||
web.window.document.addEventListener('keydown', _listener!);
|
||||
}
|
||||
|
||||
void getTopLevel() {
|
||||
print("started top");
|
||||
int highest = 0;
|
||||
AugmentTree zoomTreeRoot = AugmentTree();
|
||||
// zoomTreeRoot.data = emailsHTML[0]; // whole thing
|
||||
// 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");
|
||||
// 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);
|
||||
// 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);
|
||||
// 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);
|
||||
// }
|
||||
|
||||
Widget _buildForZooms(int lvl) {
|
||||
this.level = lvl;
|
||||
if (lvl < 0 || lvl >= sentinel.length) {
|
||||
return Center(child: Text("No content at level $lvl"));
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: this.sentinel[level].length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 6.0),
|
||||
child: Material(
|
||||
elevation: 1,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
surfaceTintColor: Theme.of(context).colorScheme.surfaceTint,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: MarkdownBlock(
|
||||
data: sentinel[level][index], // one string of markdown
|
||||
config: MarkdownConfig
|
||||
.darkConfig, // or lightConfig depending on theme
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -217,38 +462,43 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
|
||||
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(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
// child: MarkdownWidget(data: markdown), //hmmm
|
||||
child: _buildForZooms(level),
|
||||
)
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user