works for the first item filtered

This commit is contained in:
Juan Marulanda De Los Rios 2025-06-26 03:57:34 -04:00
parent 5d4bc01a59
commit add5192b3c
7 changed files with 243 additions and 89 deletions

View File

@ -23,10 +23,15 @@ class _SonicEmailViewState extends State<SonicEmailView> {
void _scrollToNumber(String spanId) { void _scrollToNumber(String spanId) {
AugmentClasses.handleJump(spanId); AugmentClasses.handleJump(spanId);
} }
void _handleViewspecs(String queryViewspecs) { void _handleViewspecs(String queryViewspecs) {
return; return;
} }
void _handleFiltering(String query) {
return;
}
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -92,9 +97,10 @@ class _SonicEmailViewState extends State<SonicEmailView> {
Column( Column(
children: [ children: [
EmailToolbar( EmailToolbar(
onButtonPressed: () => {}, onButtonPressed: () => {},
onJumpToNumbering: _scrollToNumber, onJumpToNumbering: _scrollToNumber,
onViewspecs: _handleViewspecs onViewspecs: _handleViewspecs,
onFiltering: _handleFiltering,
), ),
Row( Row(
// title of email // title of email

View File

@ -9,10 +9,15 @@ class EmailToolbar extends StatefulWidget {
final Function(String) onJumpToNumbering; final Function(String) onJumpToNumbering;
final Function(String) onViewspecs; final Function(String) onViewspecs;
final VoidCallback onButtonPressed; final VoidCallback onButtonPressed;
final Function(String) onFiltering;
EmailToolbar( EmailToolbar({
{Key? key, required this.onButtonPressed, required this.onJumpToNumbering, required this.onViewspecs}) Key? key,
: super(key: key); required this.onButtonPressed,
required this.onJumpToNumbering,
required this.onViewspecs,
required this.onFiltering,
}) : super(key: key);
@override @override
_DynamicClassesAugment createState() => _DynamicClassesAugment(); _DynamicClassesAugment createState() => _DynamicClassesAugment();
@ -196,7 +201,7 @@ class _DynamicClassesAugment extends State<EmailToolbar> {
), ),
), ),
ElevatedButton( ElevatedButton(
onPressed: () => AugmentClasses.FilterButton(context), onPressed: () => AugmentClasses().filterButton(context, widget.onFiltering),
child: Text('Filter'), child: Text('Filter'),
), ),
SizedBox(width: 8), SizedBox(width: 8),
@ -702,7 +707,6 @@ class AugmentClasses {
ElevatedButton(onPressed: () {}, child: Text('OK')), ElevatedButton(onPressed: () {}, child: Text('OK')),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
// AugmentClasses.disableIframePointerEvents();
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
child: Text('Cancel')), child: Text('Cancel')),
@ -720,61 +724,92 @@ class AugmentClasses {
}); });
} }
void handleFilter() {} Future<List<AugmentTree>> searchFilter(String query) async {
static Future<void> FilterButton(context) async { return [];
}
Future<void> filterButton(context, Function(String) onFilteringCallback) async {
//this is literally ctrl+F :skull: //this is literally ctrl+F :skull:
//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
bool? numbering = false;
String filterQueue = '';
// AugmentClasses.disableIframePointerEvents();
await showDialog( await showDialog(
context: context, context: context,
builder: (context) => Container( builder: (BuildContext dialogContext) {
height: 150, // => Container(
width: 300, // height: 150,
child: AlertDialog( // width: 300,
title: Text('Filter'), // child:
content: Container( return StatefulBuilder(builder:
width: 400, // Set the width to simulate the Windows style (BuildContext statefulBuilderContext, StateSetter setState) {
child: Column( return AlertDialog(
mainAxisSize: MainAxisSize.min, title: const Text('Filter'),
crossAxisAlignment: CrossAxisAlignment.start, content: SizedBox(
children: [ width: 400, // Set the width to simulate the Windows style
Text('Set filter:'), child: Column(
SizedBox( mainAxisSize: MainAxisSize.min,
width: 175, crossAxisAlignment: CrossAxisAlignment.start,
child: TextField( children: [
maxLines: 1, const Text('Set filter:'),
decoration: InputDecoration( SizedBox(
border: OutlineInputBorder(), width: 175,
), child: TextField(
maxLines: 1,
decoration: const InputDecoration(
border: OutlineInputBorder(),
), ),
) onChanged: (value) {
], print(value);
))))); filterQueue = value;
},
),
),
SizedBox(
height: 10,
),
Column(children: [
Row(children: [
Checkbox(
value: numbering,
activeColor:
Theme.of(context).colorScheme.tertiary,
onChanged: (newBool) {
setState(() {
numbering = newBool;
});
}),
Text("Start at top of file")
]),
]),
])),
actions: [
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text("Cancel")),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop({
'filterQueue': filterQueue,
'numbering': numbering,
});
},
child: Text("Apply")),
],
);
});
},
).then((result) {
if (result != null) {
print("filter done $result");
final String query = result['filterQueue'];
onFilteringCallback(query);
} else {
print('cancelled');
}
});
} }
// static void disableIframePointerEvents() {
// //pretty sure these dont work
// // final iframes = html.document.getElementsByTagName('iframe');
// final iframes = web.document.getElementsByTagName('iframe');
// for (var iframe in iframes) {
// // if (iframe is html.Element) {
// // iframe.style.pointerEvents = 'none'; // Disable pointer events
// if (iframe is web.Element) {
// iframe.
// }
// }
// }
// static void enableIframePointerEvents() {
// // final iframes = html.document.getElementsByTagName('iframe');
// final iframes = html.document.getElementsByTagName('iframe');
// for (var iframe in iframes) {
// if (iframe is html.Element) {
// iframe.style.pointerEvents = 'auto'; // Re-enable pointer events
// }
// }
// }
} }

View File

@ -12,13 +12,15 @@ class CollapsableEmails extends StatefulWidget {
final String threadIDs; final String threadIDs;
final String? targetJumpNumbering; final String? targetJumpNumbering;
final String? targetViewspecs; final String? targetViewspecs;
final String? targetFiltering;
CollapsableEmails( CollapsableEmails({
{required this.thread, required this.thread,
required this.threadMarkdown, required this.threadMarkdown,
required this.threadIDs, required this.threadIDs,
this.targetJumpNumbering, this.targetJumpNumbering,
this.targetViewspecs, this.targetViewspecs,
this.targetFiltering,
}); });
@override @override
@ -59,7 +61,6 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
static bool rightNumbering = true; static bool rightNumbering = true;
bool showWhole = false; bool showWhole = false;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -69,6 +70,7 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
_serializableData(widget.threadIDs); // this _serializableData(widget.threadIDs); // this
_markdown2Tree(widget.threadMarkdown); _markdown2Tree(widget.threadMarkdown);
} }
@override @override
void didUpdateWidget(covariant CollapsableEmails oldWidget) { void didUpdateWidget(covariant CollapsableEmails oldWidget) {
// TODO: implement didUpdateWidget // TODO: implement didUpdateWidget
@ -294,6 +296,7 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
}, },
); );
} }
void _handleJump(String queryNumbering) { void _handleJump(String queryNumbering) {
print(queryNumbering); print(queryNumbering);
if (queryNumbering.isEmpty) { if (queryNumbering.isEmpty) {
@ -416,12 +419,11 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
), ),
if (isExpanded) if (isExpanded)
ConstrainedBox( ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
minHeight: 100, minHeight: 100,
maxHeight: maxHeight: MediaQuery.of(context).size.height * 0.6,
MediaQuery.of(context).size.height * 0.6, ),
), child: _buildForZooms(index),
child: _buildForZooms(index),
), ),
Divider(), Divider(),
], ],

View File

@ -9,7 +9,7 @@ class CollapsableEmails extends StatefulWidget {
CollapsableEmails( CollapsableEmails(
{required this.thread, {required this.thread,
required this.threadMarkdown, required this.threadMarkdown,
required this.threadIDs, String? targetJumpNumbering, String? targetViewspecs}); required this.threadIDs, String? targetJumpNumbering, String? targetViewspecs, String? targetFiltering});
@override @override
State<CollapsableEmails> createState() => _CollapsableEmailsState(); State<CollapsableEmails> createState() => _CollapsableEmailsState();

View File

@ -13,6 +13,7 @@ class CollapsableEmails extends StatefulWidget {
final String threadIDs; final String threadIDs;
final String? targetJumpNumbering; final String? targetJumpNumbering;
final String? targetViewspecs; final String? targetViewspecs;
final String? targetFiltering;
const CollapsableEmails({ const CollapsableEmails({
required this.thread, required this.thread,
@ -21,6 +22,7 @@ class CollapsableEmails extends StatefulWidget {
required this.threadIDs, required this.threadIDs,
this.targetJumpNumbering, this.targetJumpNumbering,
this.targetViewspecs, this.targetViewspecs,
this.targetFiltering,
}); });
@override @override
@ -53,13 +55,16 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
int level = 0; int level = 0;
AugmentTree zoomTreeRoot = AugmentTree(); AugmentTree zoomTreeRoot = AugmentTree();
// late AugmentTree currentZoomNode; // late AugmentTree currentZoomNode;
late List<AugmentTree> currentZoomTree = []; late List<AugmentTree> currentZoomTree =
[]; // holds a list of list that holds the list of nodes on the currentzoom
bool zoomOut = false; bool zoomOut = false;
bool zoomIn = true; bool zoomIn = true;
late List<AugmentTree> threadNodes = []; late List<AugmentTree> threadNodes = [];
static bool leftNumbering = true; static bool leftNumbering = true;
static bool rightNumbering = true; static bool rightNumbering = true;
bool showWhole = false; bool showWhole = false;
List<AugmentTree> queryResults = [];
bool _isFilteringActive = false;
@override @override
void initState() { void initState() {
@ -83,6 +88,10 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
widget.targetViewspecs != oldWidget.targetViewspecs) { widget.targetViewspecs != oldWidget.targetViewspecs) {
_handleViewspecs(widget.targetViewspecs!); _handleViewspecs(widget.targetViewspecs!);
} }
if (widget.targetFiltering != null &&
widget.targetFiltering != oldWidget.targetFiltering) {
_handleFilterQuery(zoomTreeRoot, widget.targetFiltering!);
}
} }
@override @override
@ -90,17 +99,6 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
super.dispose(); super.dispose();
} }
// void _markdownConverter() async {
// // to list of markdown
// // for (int email = 0; email < widget.threadHTML.length; email++) {
// // String markdown = html2md.convert(widget.threadHTML[email]);
// // allMarkdown.add(markdown);
// // }
// for (int email = 0; email < widget.threadMarkdown.length; email++) {
// allMarkdown.add(email);
// }
// }
void _add2Tree(AugmentTree tree, md.Element node2add) { void _add2Tree(AugmentTree tree, md.Element node2add) {
// adds node to its corresponding place // adds node to its corresponding place
AugmentTree newNode = AugmentTree(); AugmentTree newNode = AugmentTree();
@ -228,15 +226,89 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
} }
Widget _buildForZooms(int indexThread) { Widget _buildForZooms(int indexThread) {
// IF I GIVE IT THE INDEX????
if (!_isLoaded) { if (!_isLoaded) {
return const Center(child: CircularProgressIndicator()); // loading screen return const Center(child: CircularProgressIndicator()); // loading screen
} }
final AugmentTree currentZoomNodeForThisEmail = final AugmentTree
currentZoomNodeForThisEmail = //each index is an email in the thread
currentZoomTree[indexThread]; currentZoomTree[indexThread];
print(currentZoomNodeForThisEmail.data);
print(currentZoomNodeForThisEmail.children);
print(currentZoomNodeForThisEmail.parent);
final canZoomOut = currentZoomNodeForThisEmail.parent != null; final canZoomOut = currentZoomNodeForThisEmail.parent != null;
if (currentZoomNodeForThisEmail.children.isEmpty) {
return ListView.builder(
itemCount: 1,
itemBuilder: (context, index) {
final childNode = currentZoomNodeForThisEmail;
// final childNode = currentZoomNodeForThisEmail.children[index];
final canZoomIn = childNode.children.isNotEmpty;
// currentZoomNodeForThisEmail.addNumbering();
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.surfaceBright,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
spacing: 4.0,
children: [
OutlinedButton(
onPressed:
canZoomOut ? () => _goToParent(indexThread) : null,
child: Icon(Icons.north_west_sharp),
),
OutlinedButton(
onPressed: canZoomIn
? () => _goToChildren(indexThread, index)
: null,
child: Icon(Icons.south_east_sharp),
),
],
),
SizedBox(width: 12.0),
if (leftNumbering)
Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 5, 0),
child: Text(
childNode.numbering,
style:
TextStyle(color: Color(Colors.purple[400]!.value)),
),
),
Expanded(
child: MarkdownBlock(
data: childNode.data,
config: MarkdownConfig
.darkConfig, // or lightConfig depending on theme
),
),
if (rightNumbering)
Padding(
padding: const EdgeInsets.fromLTRB(5, 10, 5, 0),
child: Text(
childNode.numbering,
style:
TextStyle(color: Color(Colors.purple[400]!.value)),
),
),
],
),
),
),
);
},
);
}
return ListView.builder( return ListView.builder(
itemCount: currentZoomNodeForThisEmail.children.length, itemCount: currentZoomNodeForThisEmail.children.length,
@ -285,8 +357,6 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
Expanded( Expanded(
child: MarkdownBlock( child: MarkdownBlock(
data: childNode.data, data: childNode.data,
// data: currentZoomNode
// .children[index].data, // one string of markdown
config: MarkdownConfig config: MarkdownConfig
.darkConfig, // or lightConfig depending on theme .darkConfig, // or lightConfig depending on theme
), ),
@ -389,6 +459,34 @@ class _CollapsableEmailsState extends State<CollapsableEmails> {
// } // }
} }
void _findNodesContainingStrDFS(
AugmentTree node, String query, List<AugmentTree> results) {
if (node.data.contains(query)) {
results.add(node);
}
for (var child in node.children) {
_findNodesContainingStrDFS(child, query, results);
}
}
List<AugmentTree> _handleFilterQuery(AugmentTree root, String query) {
List<AugmentTree> results = [];
final int targetEmailIndex = _expandedEmails.first;
_findNodesContainingStrDFS(root, query, results);
print(results);
for (var res in results) {
print(res.data);
}
if (results.isNotEmpty) {
setState(() {
currentZoomTree[targetEmailIndex] = results.first; // Update the state
_isFilteringActive = true;
});
print(currentZoomTree);
}
return results;
}
AugmentTree? _findNodeByNumbering(AugmentTree root, String numbering) { AugmentTree? _findNodeByNumbering(AugmentTree root, String numbering) {
//recursively finds the node you mentioned //recursively finds the node you mentioned
// to find the AugmentTree node corresponding to the `numbering`. // to find the AugmentTree node corresponding to the `numbering`.

View File

@ -47,6 +47,10 @@ class _EmailViewState extends State<EmailView> {
} }
void _filteringQuery(String query){
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -61,7 +65,7 @@ class _EmailViewState extends State<EmailView> {
onButtonPressed: () => {}, onButtonPressed: () => {},
onJumpToNumbering: _scrollToNumber, onJumpToNumbering: _scrollToNumber,
onViewspecs: _viewSpecs, onViewspecs: _viewSpecs,
onFiltering: _filteringQuery,
), ),
Row( Row(
children: [ children: [

View File

@ -44,6 +44,7 @@ class _EmailViewState extends State<EmailView> {
]; ];
String? _targetJumpNumbering; String? _targetJumpNumbering;
String? _targetViewspecs; String? _targetViewspecs;
String? _queryFiltering;
@override @override
void initState() { void initState() {
@ -71,6 +72,12 @@ class _EmailViewState extends State<EmailView> {
}); });
} }
void _handleFiltering(String query) {
setState(() {
_queryFiltering = query;
});
}
// TODO: void _invisibility(String ) //to make purple numbers not visible // TODO: void _invisibility(String ) //to make purple numbers not visible
@override @override
@ -88,6 +95,7 @@ class _EmailViewState extends State<EmailView> {
onJumpToNumbering: _handleJumpRequest, onJumpToNumbering: _handleJumpRequest,
onViewspecs: _handleViewspecsRequest, onViewspecs: _handleViewspecsRequest,
onButtonPressed: () => {print("email tool bar pressed")}, onButtonPressed: () => {print("email tool bar pressed")},
onFiltering: _handleFiltering,
), ),
Row( Row(
// title of email // title of email
@ -133,6 +141,7 @@ class _EmailViewState extends State<EmailView> {
threadIDs: widget.id, threadIDs: widget.id,
targetJumpNumbering: _targetJumpNumbering, targetJumpNumbering: _targetJumpNumbering,
targetViewspecs: _targetViewspecs, targetViewspecs: _targetViewspecs,
targetFiltering: _queryFiltering,
), ),
), ),
], ],