From a65c973dc74be72457fb4422f37971362045922c Mon Sep 17 00:00:00 2001 From: juan Date: Thu, 24 Apr 2025 17:01:19 -0400 Subject: [PATCH 01/19] rename and delete api calls --- lib/api_service.dart | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/lib/api_service.dart b/lib/api_service.dart index 1777c9c..37b6736 100644 --- a/lib/api_service.dart +++ b/lib/api_service.dart @@ -122,8 +122,8 @@ class ApiService { if (response.statusCode == 200) { content += response.body; try { - List attachments = await getAttachmentsInfo( - emailFolder, id); + List 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 @@ -164,6 +164,31 @@ class ApiService { Map requestBody = {'name': folderName}; + try { + var response = await http.post( + url, + headers: { + 'Content-Type': 'application/json', + }, + body: jsonEncode(requestBody), + ); + if (response.statusCode == 200) { + print('response body: ${response.body}'); + } else { + print('Error: ${response.statusCode}, response body: ${response.body}'); + } + } catch (e) { + print('error making post req: $e'); + } + } + + Future renameFolder(String oldFolder, String newFolder) async { + var url = Uri.http('$ip:$port', 'rename_folder'); + Map requestBody = { + 'old_name': oldFolder, + 'new_name': newFolder, + }; + try { var response = await http.post( url, @@ -268,7 +293,6 @@ class ApiService { //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"); // JavaScript code embedded as a string String jsCode = ''' @@ -379,7 +403,7 @@ class _EmailViewState extends State { String currentContent = widget.emailContent; viewTypeId = "iframe-${DateTime.now().millisecondsSinceEpoch}"; _registerViewFactory(currentContent); - _markerPositionsFuture = ApiService().getMarkerPosition(); + _markerPositionsFuture = ApiService().getMarkerPosition(); } void _registerViewFactory(String currentContent) { From a7c30732f47fe4a6ff775ac83565bf4bbdc57a50 Mon Sep 17 00:00:00 2001 From: juan Date: Thu, 24 Apr 2025 17:01:46 -0400 Subject: [PATCH 02/19] alerDialog widget for renaming --- lib/folder_drawer.dart | 100 +++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 33 deletions(-) diff --git a/lib/folder_drawer.dart b/lib/folder_drawer.dart index 62b0a42..257a98d 100644 --- a/lib/folder_drawer.dart +++ b/lib/folder_drawer.dart @@ -16,6 +16,7 @@ class FolderDrawer extends StatefulWidget { class _FolderDrawerState extends State { List folders = []; + final TextEditingController _renameController = TextEditingController(); @override void initState() { @@ -48,7 +49,7 @@ class _FolderDrawerState extends State { icon: Icon(Icons.more_vert), onPressed: () => { ///show options - _showOptions(context) + _showOptions(context, folder) }, ), onTap: () { @@ -65,7 +66,7 @@ class _FolderDrawerState extends State { showDialog( context: context, builder: (BuildContext context) { - return NewMailbox(apiService: widget.apiService); + return NewMailbox(apiService: widget.apiService); }, ); // Navigator.of(context).pop(); @@ -83,39 +84,74 @@ class _FolderDrawerState extends State { ), ); } - void _showOptions(BuildContext context) async { - final RenderBox overlay = Overlay.of(context).context.findRenderObject() as RenderBox; - - await showMenu( - context: context, - position: RelativeRect.fromLTRB(100, 100, overlay.size.width, overlay.size.height), - items: >[ - PopupMenuItem( - value: 'Rename', - child: Text('Rename Folder'), - ), - PopupMenuItem( - value: 'Delete', - child: Text('Delete Folder'), - ), - ], - ).then((value) { - // Handle the action based on the selected menu item - if (value == 'Rename') { - // Logic for renaming the folder - print('Rename folder'); - } else if (value == 'Delete') { - // Logic for deleting the folder - print('Delete folder'); - } - }); -} + Future _renameDialog(String oldFolder) async { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text("Rename Mailbox"), + content: TextField( + controller: _renameController, + decoration: const InputDecoration( + hintText: "New Name", + ), + ), + actions: [ + TextButton( + onPressed: () { + String newfolderName = _renameController.text; + if (newfolderName.isNotEmpty) { + //make an and to make sure there's two folders with the same name + ApiService().renameFolder(oldFolder, newfolderName); + } + Navigator.of(context).pop(); + }, + child: const Text("Rename"), + ) + ], + ); + }); + + return false; + } + + void _showOptions(BuildContext context, String folderName) async { + final RenderBox overlay = + Overlay.of(context).context.findRenderObject() as RenderBox; + print(folderName); + await showMenu( + context: context, + position: RelativeRect.fromLTRB( + 100, 100, overlay.size.width, overlay.size.height), + items: >[ + PopupMenuItem( + value: 'Rename', + child: Text('Rename Folder'), + ), + PopupMenuItem( + value: 'Delete', + child: Text('Delete Folder'), + ), + ], + ).then((value) { + // Handle the action based on the selected menu item + if (value == 'Rename') { + // Logic for renaming the folder + print('Rename folder $folderName'); + _renameDialog(folderName); + } else if (value == 'Delete') { + // Logic for deleting the folder + print("Deleting $folderName"); + ApiService().deleteFolder(folderName); + print('Deleted folder'); + } + }); + } } class NewMailbox extends StatelessWidget { final ApiService apiService; - // final Function(String) onFolderCreated; final TextEditingController _textFieldController = TextEditingController(); NewMailbox({required this.apiService}); @@ -127,7 +163,7 @@ class NewMailbox extends StatelessWidget { content: TextField( controller: _textFieldController, decoration: const InputDecoration( - hintText: "EPIC FOLDER", // Your custom hint text here + hintText: "New Folder", ), ), actions: [ @@ -138,9 +174,7 @@ class NewMailbox extends StatelessWidget { if (folderName.isNotEmpty) { apiService.createFolder(folderName); - // onFolderCreated(folderName); } - // apiService.createFolder(_textFieldController.text); Navigator.of(context).pop(); }, child: const Text("Approve"), From e104f445ab1c6ee1b25957c6ee3da349aa10f1ef Mon Sep 17 00:00:00 2001 From: juan Date: Mon, 28 Apr 2025 20:08:35 -0400 Subject: [PATCH 03/19] confirm dialog when deleting a folder --- lib/folder_drawer.dart | 81 ++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/lib/folder_drawer.dart b/lib/folder_drawer.dart index 257a98d..edc7eca 100644 --- a/lib/folder_drawer.dart +++ b/lib/folder_drawer.dart @@ -90,32 +90,62 @@ class _FolderDrawerState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text("Rename Mailbox"), - content: TextField( - controller: _renameController, - decoration: const InputDecoration( - hintText: "New Name", - ), - ), - actions: [ - TextButton( - onPressed: () { - String newfolderName = _renameController.text; - if (newfolderName.isNotEmpty) { - //make an and to make sure there's two folders with the same name - ApiService().renameFolder(oldFolder, newfolderName); - } - Navigator.of(context).pop(); - }, - child: const Text("Rename"), - ) - ], - ); + title: Text("Rename Mailbox"), + content: TextField( + controller: _renameController, + decoration: const InputDecoration( + hintText: "New Name", + ), + ), + actions: [ + TextButton( + onPressed: () { + String newfolderName = _renameController.text; + if (newfolderName.isNotEmpty) { + //make an and to make sure there's two folders with the same name + ApiService().renameFolder(oldFolder, newfolderName); + } + Navigator.of(context).pop(); + }, + child: const Text("Rename"), + ), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text("Cancel"), + ) + ], + ); }); return false; } + Future doubleCheckDelete(String folderTobeDeleted) async { + return showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + title: Text("Confirm delete of: $folderTobeDeleted"), + actions: [ + TextButton( + onPressed: () { + ApiService().deleteFolder(folderTobeDeleted); + Navigator.of(context).pop(); + }, + child: Text("Yes")), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text("No")), + ], + ); + }); + } + void _showOptions(BuildContext context, String folderName) async { final RenderBox overlay = Overlay.of(context).context.findRenderObject() as RenderBox; @@ -143,7 +173,8 @@ class _FolderDrawerState extends State { } else if (value == 'Delete') { // Logic for deleting the folder print("Deleting $folderName"); - ApiService().deleteFolder(folderName); + doubleCheckDelete(folderName); + // ApiService().deleteFolder(folderName); print('Deleted folder'); } }); @@ -179,6 +210,12 @@ class NewMailbox extends StatelessWidget { }, child: const Text("Approve"), ), + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text("Cancel"), + ) ], ); } From b5cb5b99fbe30133dc75cd25df4108de6424236b Mon Sep 17 00:00:00 2001 From: juan Date: Fri, 2 May 2025 19:35:51 -0400 Subject: [PATCH 04/19] fixed problem of pagenation not updating --- lib/email.dart | 282 +++++++------- lib/home_page.dart | 894 +++++++++++++++++++++++---------------------- 2 files changed, 600 insertions(+), 576 deletions(-) diff --git a/lib/email.dart b/lib/email.dart index e289526..5a4c396 100644 --- a/lib/email.dart +++ b/lib/email.dart @@ -1,136 +1,146 @@ -import 'package:flutter/material.dart'; -import 'api_service.dart'; -import 'structs.dart'; - -class EmailListScreen extends StatelessWidget { - final List emails; - final Future Function(List, String) getEmailContent; - final String folder; - - - EmailListScreen({required this.emails, required this.getEmailContent, required this.folder}); -//fix the email list - @override - Widget build(BuildContext context) { - return Scaffold( - body: ListView.separated( - itemCount: emails.length, - itemBuilder: (context, index) { - final email = emails[index]; - return ListTile( - title: Text(email.from_name, - style: TextStyle(fontWeight: FontWeight.bold)), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [Text(email.subject)], - ), - trailing: Text(email.date.toString()), - onTap: () async { - String emailContent = await getEmailContent(email.messages, folder); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => EmailView( - emailContent: emailContent, - from: email.from_address, - name: email.from_name, - to: email.to.toString(), - subject: email.subject, - date: email.date.toString(), - id: email.id.toString(), - ), - ), - ); - }, - ); - }, - separatorBuilder: (context, index) => Divider(), - ), - ); - } -} - -// ignore: must_be_immutable -class EmailPage extends StatefulWidget { - EmailPage({Key? key}) : super(key: key); - String selectedFolder = "INBOX"; //starter - int offset = 0; - int page = 1; - - @override - EmailPageState createState() => EmailPageState(); -} - -class EmailPageState extends State { - final ApiService apiService = ApiService(); - List emails = []; - int page = 1; - bool isBackDisabled = false; - - @override - void initState() { - super.initState(); - widget.page = page; - isBackDisabled = true; - } - - void updateSelectedFolder(String folder) { - setState(() { - widget.selectedFolder = folder; - }); - print(folder); - _fetchEmails(); - } - - String getPage() { - return widget.page.toString(); - } - - void updatePagenation(String option) { - if (option == "next") { - setState(() { - widget.offset += 50; - widget.page += 1; - isBackDisabled = false; - }); - } else if (option == "back") { - setState(() { - widget.offset -= 50; - widget.page -= 1; - if (widget.page == 1) { - isBackDisabled = true; - print("back dis"); - } - }); - } - // print(currentPage); - _fetchEmails(); - } - - void _fetchEmails() async { - // print(selectedFolder) - try { - List fetchedEmails = await apiService - .fetchEmailsFromFolder(widget.selectedFolder, widget.offset); - if (!mounted) return; - - setState(() { - emails = fetchedEmails; // Update the list of emails - }); - } catch (e) { - print('Error fetching emails: $e'); - } - } - - @override - Widget build(BuildContext context) { - _fetchEmails(); - return Scaffold( - body: EmailListScreen( - emails: emails, - getEmailContent: apiService.fetchEmailContent, - folder: widget.selectedFolder,//try to grab from it directly - ), - ); - } -} +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'api_service.dart'; +import 'structs.dart'; + +class EmailListScreen extends StatelessWidget { + final List emails; + final Future Function(List, String) getEmailContent; + final String folder; + + EmailListScreen( + {required this.emails, + required this.getEmailContent, + required this.folder}); +//fix the email list + @override + Widget build(BuildContext context) { + return Scaffold( + body: ListView.separated( + itemCount: emails.length, + itemBuilder: (context, index) { + final email = emails[index]; + return ListTile( + title: Text(email.from_name, + style: TextStyle(fontWeight: FontWeight.bold)), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [Text(email.subject)], + ), + trailing: Text(email.date.toString()), + onTap: () async { + String emailContent = + await getEmailContent(email.messages, folder); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => EmailView( + emailContent: emailContent, + from: email.from_address, + name: email.from_name, + to: email.to.toString(), + subject: email.subject, + date: email.date.toString(), + id: email.id.toString(), + ), + ), + ); + }, + ); + }, + separatorBuilder: (context, index) => Divider(), + ), + ); + } +} + +// ignore: must_be_immutable +class EmailPage extends StatefulWidget { + EmailPage({Key? key}) : super(key: key); + String selectedFolder = "INBOX"; //starter + int offset = 0; + int page = 1; + + @override + EmailPageState createState() => EmailPageState(); +} + +class EmailPageState extends State { + final ApiService apiService = ApiService(); + List emails = []; + ValueNotifier currentPageNotifier = ValueNotifier(1); + int page = 1; + bool isBackDisabled = false; + + @override + void initState() { + super.initState(); + widget.page = page; + isBackDisabled = true; + } + + String getPage() => widget.page.toString(); + bool get backDisabled => isBackDisabled; + + void updateSelectedFolder(String folder) { + setState(() { + widget.selectedFolder = folder; + }); + print(folder); + _fetchEmails(); + } + + // String getPage() => widget.page.toString(); + + + void updatePagenation(String option) { + if (option == "next") { + setState(() { + widget.offset += 50; + widget.page += 1; + currentPageNotifier.value = widget.page; + isBackDisabled = false; + }); + } else if (option == "back") { + setState(() { + widget.offset -= 50; + widget.page -= 1; + currentPageNotifier.value = widget.page; + if (widget.page == 1) { + isBackDisabled = true; + print("back dis"); + } + }); + } + // print(currentPage); + print(widget.page); + _fetchEmails(); + } + + void _fetchEmails() async { + // print(selectedFolder) + try { + List fetchedEmails = await apiService + .fetchEmailsFromFolder(widget.selectedFolder, widget.offset); + if (!mounted) return; + + setState(() { + emails = fetchedEmails; // Update the list of emails + }); + } catch (e) { + print('Error fetching emails: $e'); + } + } + + @override + Widget build(BuildContext context) { + _fetchEmails(); + return Scaffold( + body: EmailListScreen( + emails: emails, + getEmailContent: apiService.fetchEmailContent, + folder: widget.selectedFolder, //try to grab from it directly + ), + ); + } +} diff --git a/lib/home_page.dart b/lib/home_page.dart index 5badb9f..03ae481 100644 --- a/lib/home_page.dart +++ b/lib/home_page.dart @@ -1,440 +1,454 @@ -import 'folder_drawer.dart'; -import 'structs.dart'; -import 'package:flutter/widgets.dart'; -import 'api_service.dart'; -import 'package:flutter/material.dart'; -import 'email.dart'; -// import 'package:shared_preferences/shared_preferences.dart'; -// import 'serialize.dart'; - -class HomeScreen extends StatefulWidget { - @override - _HomeScreenState createState() => _HomeScreenState(); -} - -class _HomeScreenState extends State with TickerProviderStateMixin { - final GlobalKey _scaffoldKey = GlobalKey(); - final GlobalKey _emailPageKey = GlobalKey(); - ApiService apiService = ApiService(); - bool _isSidebarOpen = true; - bool querySearches = false; - String? _selectedOption = "INBOX"; - - List _tabs = ['Emails']; - Map _tabWidgets = {}; - TabController? _tabController; - - @override - void initState() { - super.initState(); - _tabController = TabController(length: _tabs.length, vsync: this); - _tabWidgets['Emails'] = EmailPage( - key: _emailPageKey, - ); - } - - // Add a new tab based on the search - void _performSearch(String query, String? list) { - setState(() { - if (!_tabs.contains(query)) { - _tabs.add(query); - _tabWidgets[query] = _buildSearchResultsWidget( - query, list); // Store a different widget for this tab - _tabController = TabController(length: _tabs.length, vsync: this); - } - }); - } - - void _showOptionsSearchDialog () async { - List folders = await apiService.fetchFolders(); - - if (mounted) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text('Choose an Option'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: folders.map((option) { - return ListTile( - title: Text(option), - leading: Radio( - value: option, - groupValue: _selectedOption, // Bind with _selectedOption - onChanged: (String? value) { - setState(() { - _selectedOption = value; - }); - Navigator.of(context).pop(); // Close the dialog on selection - }, - ), - ); - }).toList(), - ), - actions: [ - ElevatedButton( - child: Text('Submit'), - onPressed: () { - Navigator.of(context).pop(); // Close the dialog - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('You selected: $_selectedOption'), - )); - }, - ), - ], - ); - }, - );} - } - - - // Remove a tab - void _removeTab(int index) { - if (_tabs[index] != 'Emails') { - setState(() { - String tabToRemove = _tabs[index]; - _tabs.removeAt(index); - _tabWidgets - .remove(tabToRemove); // Remove widget associated with the tab - _tabController = TabController(length: _tabs.length, vsync: this); - }); - } - } - - // Build a custom widget for each search query - Widget _buildSearchResultsWidget(String query, String? list) { - return FutureBuilder>( - future: apiService.sonicSearch(list ?? "INBOX", 50, 0, query), - builder: (BuildContext context, - AsyncSnapshot> snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Center(child: Text('Error: ${snapshot.error}')); - } else if (!snapshot.hasData || snapshot.data!.isEmpty) { - return Center(child: Text('No results found for: $query')); - } else { - List result = snapshot.data!; - return Scaffold( - body: ListView.separated( - itemCount: result.length, - itemBuilder: (context, index) { - final SerializableMessage email = result[index]; - return ListTile( - title: Text(email.from, - style: TextStyle(fontWeight: FontWeight.bold)), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [Text(email.subject)], - ), - trailing: Text(email.date.toString()), - onTap: () async { - // print('tapped'); - String emailContent = - await apiService.fetchEmailContent([email.id], email.list); - // print('content below'); - // print(emailContent); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => EmailView( - emailContent: emailContent, - from: email.from, - name: email.name, - to: email.to.toString(), - subject: email.subject, - date: email.date.toString(), - id: email.id.toString(), - ), - ), - ); - }, - ); - }, - separatorBuilder: (context, index) => Divider(), - ), - // child: Column( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // Text("Results for: $query", style: TextStyle(fontSize: 24)), - // // Display the actual data - // Text(result[0].name), // Accessing the first result safely - // Text(result[0].from), // Displaying the 'from' field as an example - // Text(result[0].hash), - // Text(result[0].subject), - // Text(result[0].uid.toString()), - // Text(result[0].list), - // Text(result[0].id), - - // // Add more fields or customize the display - // // SerializableEmailListScreen(emails: result, getEmailContent: getEmailContent) - // // Expanded( - - // // child: - // // ), - // ], - ); - // ); - } - }, - ); - } - - @override - void dispose() { - _tabController?.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - key: _scaffoldKey, - drawer: FolderDrawer( - apiService: apiService, - onFolderTap: (folder) { - _emailPageKey.currentState?.updateSelectedFolder(folder); - }, - ), - body: Stack( - children: [ - Row( - children: [ - // Sidebar - if (_isSidebarOpen) - Container( - width: 70, - color: Color.fromARGB(17, 96, 122, 135), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ListTile( - leading: Icon(Icons.home), - onTap: () { - // Navigate to Home - }, - ), - ListTile( - leading: Icon(Icons.settings), - onTap: () { - // Navigate to Settings - }, - ), - ListTile( - leading: Icon(Icons.email), - onTap: () { - _scaffoldKey.currentState?.openDrawer(); - }, - ), - Spacer(), - Padding( - padding: const EdgeInsets.all(8.0), - child: Align( - alignment: Alignment.bottomLeft, - child: IconButton( - icon: Icon(Icons.close, color: Colors.white), - onPressed: () { - setState(() { - _isSidebarOpen = false; - }); - }, - ), - ), - ), - ], - ), - ), - // Main content - Expanded( - child: Column( - children: [ - Container( - padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 4.0), - color: Color.fromARGB(42, 36, 102, 132), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 800, - height: 40, - child: TextField( - decoration: InputDecoration( - hintText: 'Search...', - border: OutlineInputBorder(), - prefixIcon: Icon(Icons.search), - ), - onSubmitted: (value) { - if (value.isNotEmpty) { - _performSearch(value, _selectedOption); - } - //this is the input box i mentioned - // if (value == '') { - // setState(() { - // querySearches = false; - // }); - // } - // Future> results = apiService - // .sonicSearch('INBOX', 20, 0, value); - // // print(value); - // print(results); - // setState(() { - // querySearches = true; - // }); - }, - ), - ), - SizedBox( - width: 16, - ), - Container( - width: 80, - height: 40, - child: ElevatedButton( - onPressed: _showOptionsSearchDialog, - child: Icon(Icons.manage_search), - ), - ) - ], - ), - ), - Container( - padding: EdgeInsets.all(0.0), - color: Color.fromARGB(42, 36, 102, 132), - child: Row( - children: [ - Container( - height: 2, - ) - ], - ), - ), - Container( - color: Color.fromARGB(255, 131, 110, 143), - child: TabBar( - controller: _tabController, - isScrollable: true, - tabs: _tabs - .asMap() - .entries - .map((entry) => Tab( - child: Row( - children: [ - Text(entry.value), - if (entry.value != 'Emails') - GestureDetector( - onTap: () => _removeTab(entry.key), - child: Icon(Icons.close, size: 16), - ), - ], - ), - )) - .toList(), - labelColor: Colors.white, - indicatorColor: Colors.white, - ), - ), - Container( - // alignment: Alignment.topLeft, - padding: EdgeInsets.all(8.0), - color: Colors.white, - child: Row( - children: [ - ElevatedButton( - onPressed: () { - _emailPageKey.currentState!.isBackDisabled ? null: _emailPageKey.currentState - ?.updatePagenation('back'); - }, - child: Icon(Icons.navigate_before), - ), - Text(_emailPageKey.currentState?.getPage() ?? '1'), - ElevatedButton( - onPressed: () { - _emailPageKey.currentState - ?.updatePagenation('next'); - }, - child: Icon(Icons.navigate_next), - ), - ], - ), - ), - Expanded( - child: TabBarView( - controller: _tabController, - children: _tabs.map((tab) { - return _tabWidgets[tab] ?? - Center(child: Text("No content found")); - // return Center( - // child: EmailPage( - // key: _emailPageKey, - // )); - }).toList(), - ), - ), - - // if (_tabs.isEmpty) - // Expanded( - // child: EmailPage(key: _emailPageKey), - // ), - // if (_tabs.isNotEmpty) - // Expanded( - // // child: Text('supposed to be mails'), - // child: TabBarView( - // controller: _tabController, - // children: _tabs - // .map((tab) => Center(child: Text('Results for $tab'))) - // .toList(), - // ), - // ), - ], - ), - ), - ], - ), - if (!_isSidebarOpen) - Positioned( - bottom: 16, - left: 16, - child: FloatingActionButton( - child: Icon(Icons.menu), - onPressed: () { - setState(() { - _isSidebarOpen = true; - }); - }, - ), - ), - ], - ), - ); - } -} -// void _showPopupMenu(BuildContext context, Offset position) async { -// final RenderBox overlay = -// Overlay.of(context).context.findRenderObject() as RenderBox; - -// await showMenu( -// context: context, -// position: RelativeRect.fromLTRB( -// position.dx, -// position.dy, -// overlay.size.width - position.dx, -// overlay.size.height - position.dy, -// ), -// items: >[ -// PopupMenuItem( -// value: 'Open', -// child: Text('Open'), -// ), -// PopupMenuItem( -// value: 'Reply', -// child: Text('Reply'), -// ), -// PopupMenuItem( -// value: 'Delete', -// child: Text('Delete'), -// ), -// ], -// ); -// } -// } +import 'folder_drawer.dart'; +import 'structs.dart'; +import 'package:flutter/widgets.dart'; +import 'api_service.dart'; +import 'package:flutter/material.dart'; +import 'email.dart'; +// import 'package:shared_preferences/shared_preferences.dart'; +// import 'serialize.dart'; + +class HomeScreen extends StatefulWidget { + @override + _HomeScreenState createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State with TickerProviderStateMixin { + final GlobalKey _scaffoldKey = GlobalKey(); + final GlobalKey _emailPageKey = GlobalKey(); + ApiService apiService = ApiService(); + bool _isSidebarOpen = true; + bool querySearches = false; + String? _selectedOption = "INBOX"; + + List _tabs = ['Emails']; + Map _tabWidgets = {}; + TabController? _tabController; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: _tabs.length, vsync: this); + _tabWidgets['Emails'] = EmailPage( + key: _emailPageKey, + ); + } + + // Add a new tab based on the search + void _performSearch(String query, String? list) { + setState(() { + if (!_tabs.contains(query)) { + _tabs.add(query); + _tabWidgets[query] = _buildSearchResultsWidget( + query, list); // Store a different widget for this tab + _tabController = TabController(length: _tabs.length, vsync: this); + } + }); + } + + void _showOptionsSearchDialog () async { + List folders = await apiService.fetchFolders(); + + if (mounted) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text('Choose an Option'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: folders.map((option) { + return ListTile( + title: Text(option), + leading: Radio( + value: option, + groupValue: _selectedOption, // Bind with _selectedOption + onChanged: (String? value) { + setState(() { + _selectedOption = value; + }); + Navigator.of(context).pop(); // Close the dialog on selection + }, + ), + ); + }).toList(), + ), + actions: [ + ElevatedButton( + child: Text('Submit'), + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('You selected: $_selectedOption'), + )); + }, + ), + ], + ); + }, + );} + } + + + // Remove a tab + void _removeTab(int index) { + if (_tabs[index] != 'Emails') { + setState(() { + String tabToRemove = _tabs[index]; + _tabs.removeAt(index); + _tabWidgets + .remove(tabToRemove); // Remove widget associated with the tab + _tabController = TabController(length: _tabs.length, vsync: this); + }); + } + } + + // Build a custom widget for each search query + Widget _buildSearchResultsWidget(String query, String? list) { + return FutureBuilder>( + future: apiService.sonicSearch(list ?? "INBOX", 50, 0, query), + builder: (BuildContext context, + AsyncSnapshot> snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + return Center(child: Text('No results found for: $query')); + } else { + List result = snapshot.data!; + return Scaffold( + body: ListView.separated( + itemCount: result.length, + itemBuilder: (context, index) { + final SerializableMessage email = result[index]; + return ListTile( + title: Text(email.from, + style: TextStyle(fontWeight: FontWeight.bold)), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [Text(email.subject)], + ), + trailing: Text(email.date.toString()), + onTap: () async { + // print('tapped'); + String emailContent = + await apiService.fetchEmailContent([email.id], email.list); + // print('content below'); + // print(emailContent); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => EmailView( + emailContent: emailContent, + from: email.from, + name: email.name, + to: email.to.toString(), + subject: email.subject, + date: email.date.toString(), + id: email.id.toString(), + ), + ), + ); + }, + ); + }, + separatorBuilder: (context, index) => Divider(), + ), + // child: Column( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Text("Results for: $query", style: TextStyle(fontSize: 24)), + // // Display the actual data + // Text(result[0].name), // Accessing the first result safely + // Text(result[0].from), // Displaying the 'from' field as an example + // Text(result[0].hash), + // Text(result[0].subject), + // Text(result[0].uid.toString()), + // Text(result[0].list), + // Text(result[0].id), + + // // Add more fields or customize the display + // // SerializableEmailListScreen(emails: result, getEmailContent: getEmailContent) + // // Expanded( + + // // child: + // // ), + // ], + ); + // ); + } + }, + ); + } + + @override + void dispose() { + _tabController?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + key: _scaffoldKey, + drawer: FolderDrawer( + apiService: apiService, + onFolderTap: (folder) { + _emailPageKey.currentState?.updateSelectedFolder(folder); + }, + ), + body: Stack( + children: [ + Row( + children: [ + // Sidebar + if (_isSidebarOpen) + Container( + width: 70, + color: Color.fromARGB(17, 96, 122, 135), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListTile( + leading: Icon(Icons.home), + onTap: () { + // Navigate to Home + }, + ), + ListTile( + leading: Icon(Icons.settings), + onTap: () { + // Navigate to Settings + }, + ), + ListTile( + leading: Icon(Icons.email), + onTap: () { + _scaffoldKey.currentState?.openDrawer(); + }, + ), + Spacer(), + Padding( + padding: const EdgeInsets.all(8.0), + child: Align( + alignment: Alignment.bottomLeft, + child: IconButton( + icon: Icon(Icons.close, color: Colors.white), + onPressed: () { + setState(() { + _isSidebarOpen = false; + }); + }, + ), + ), + ), + ], + ), + ), + // Main content + Expanded( + child: Column( + children: [ + Container( + padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 4.0), + color: Color.fromARGB(42, 36, 102, 132), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 800, + height: 40, + child: TextField( + decoration: InputDecoration( + hintText: 'Search...', + border: OutlineInputBorder(), + prefixIcon: Icon(Icons.search), + ), + onSubmitted: (value) { + if (value.isNotEmpty) { + _performSearch(value, _selectedOption); + } + //this is the input box i mentioned + // if (value == '') { + // setState(() { + // querySearches = false; + // }); + // } + // Future> results = apiService + // .sonicSearch('INBOX', 20, 0, value); + // // print(value); + // print(results); + // setState(() { + // querySearches = true; + // }); + }, + ), + ), + SizedBox( + width: 16, + ), + Container( + width: 80, + height: 40, + child: ElevatedButton( + onPressed: _showOptionsSearchDialog, + child: Icon(Icons.manage_search), + ), + ) + ], + ), + ), + Container( + padding: EdgeInsets.all(0.0), + color: Color.fromARGB(42, 36, 102, 132), + child: Row( + children: [ + Container( + height: 2, + ) + ], + ), + ), + Container( + color: Color.fromARGB(255, 131, 110, 143), + child: TabBar( + controller: _tabController, + isScrollable: true, + tabs: _tabs + .asMap() + .entries + .map((entry) => Tab( + child: Row( + children: [ + Text(entry.value), + if (entry.value != 'Emails') + GestureDetector( + onTap: () => _removeTab(entry.key), + child: Icon(Icons.close, size: 16), + ), + ], + ), + )) + .toList(), + labelColor: Colors.white, + indicatorColor: Colors.white, + ), + ), + Container( + // alignment: Alignment.topLeft, + padding: EdgeInsets.all(8.0), + color: Colors.white, + child: Row( + children: [ + ElevatedButton( + onPressed: () { + _emailPageKey.currentState!.isBackDisabled ? null: _emailPageKey.currentState + ?.updatePagenation('back'); + }, + child: Icon(Icons.navigate_before), + ), + Builder( + builder: (context) { + final emailState = _emailPageKey.currentState; + if (emailState == null) { + // Schedule a rebuild once the state is available + Future.microtask(() => setState(() {})); + return Text('Loading...'); + } + + return ValueListenableBuilder( + valueListenable: emailState.currentPageNotifier, + builder: (context, value, _) => Text('$value'), + ); + }, + ), + ElevatedButton( + onPressed: () { + _emailPageKey.currentState + ?.updatePagenation('next'); + }, + child: Icon(Icons.navigate_next), + ), + ], + ), + ), + Expanded( + child: TabBarView( + controller: _tabController, + children: _tabs.map((tab) { + return _tabWidgets[tab] ?? + Center(child: Text("No content found")); + // return Center( + // child: EmailPage( + // key: _emailPageKey, + // )); + }).toList(), + ), + ), + + // if (_tabs.isEmpty) + // Expanded( + // child: EmailPage(key: _emailPageKey), + // ), + // if (_tabs.isNotEmpty) + // Expanded( + // // child: Text('supposed to be mails'), + // child: TabBarView( + // controller: _tabController, + // children: _tabs + // .map((tab) => Center(child: Text('Results for $tab'))) + // .toList(), + // ), + // ), + ], + ), + ), + ], + ), + if (!_isSidebarOpen) + Positioned( + bottom: 16, + left: 16, + child: FloatingActionButton( + child: Icon(Icons.menu), + onPressed: () { + setState(() { + _isSidebarOpen = true; + }); + }, + ), + ), + ], + ), + ); + } +} +// void _showPopupMenu(BuildContext context, Offset position) async { +// final RenderBox overlay = +// Overlay.of(context).context.findRenderObject() as RenderBox; + +// await showMenu( +// context: context, +// position: RelativeRect.fromLTRB( +// position.dx, +// position.dy, +// overlay.size.width - position.dx, +// overlay.size.height - position.dy, +// ), +// items: >[ +// PopupMenuItem( +// value: 'Open', +// child: Text('Open'), +// ), +// PopupMenuItem( +// value: 'Reply', +// child: Text('Reply'), +// ), +// PopupMenuItem( +// value: 'Delete', +// child: Text('Delete'), +// ), +// ], +// ); +// } +// } From b2fd9d16cc0ea310f9632e476fdc3f989beb9815 Mon Sep 17 00:00:00 2001 From: juan Date: Wed, 7 May 2025 16:17:43 -0400 Subject: [PATCH 05/19] move_email endpoint --- lib/api_service.dart | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/lib/api_service.dart b/lib/api_service.dart index 37b6736..75f21a8 100644 --- a/lib/api_service.dart +++ b/lib/api_service.dart @@ -143,10 +143,32 @@ class ApiService { return content; } - // void _addMailBox async(BuildContext context){ - // //add email folder - // showDialog(context: context, builder: builder) - // } + Future moveEmail(String fromFolder, String uID, String toFolder) async { + var url = Uri.http('$ip:$port', 'move_email'); + Map requestBody = { + 'from': fromFolder, + 'uid': uID, + 'to': toFolder, + }; + try { + var response = await http.post( + url, + headers: { + 'Content-Type': 'application/json', + }, + body: jsonEncode(requestBody), + ); + if (response.statusCode == 200) { + print('response body ${response.body}'); + return true; + } else { + print('error '); + } + } catch (e) { + print(e); + } + return false; + } Future> fetchFolders() async { try { @@ -176,7 +198,7 @@ class ApiService { print('response body: ${response.body}'); } else { print('Error: ${response.statusCode}, response body: ${response.body}'); - } + } } catch (e) { print('error making post req: $e'); } From 2677625b5461d8ed718e59d5bd805da4d6017250 Mon Sep 17 00:00:00 2001 From: juan Date: Thu, 8 May 2025 01:06:53 -0400 Subject: [PATCH 06/19] fixed issue that at rebuild it would go in a roulete of fetching emails every time --- lib/email.dart | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/email.dart b/lib/email.dart index 5a4c396..12b9b83 100644 --- a/lib/email.dart +++ b/lib/email.dart @@ -41,7 +41,7 @@ class EmailListScreen extends StatelessWidget { to: email.to.toString(), subject: email.subject, date: email.date.toString(), - id: email.id.toString(), + id: email.id.toString(), //i think this is thread id? ), ), ); @@ -77,6 +77,7 @@ class EmailPageState extends State { super.initState(); widget.page = page; isBackDisabled = true; + _fetchEmails(); } String getPage() => widget.page.toString(); @@ -91,7 +92,6 @@ class EmailPageState extends State { } // String getPage() => widget.page.toString(); - void updatePagenation(String option) { if (option == "next") { @@ -108,7 +108,7 @@ class EmailPageState extends State { currentPageNotifier.value = widget.page; if (widget.page == 1) { isBackDisabled = true; - print("back dis"); + print("back disabled"); } }); } @@ -118,7 +118,6 @@ class EmailPageState extends State { } void _fetchEmails() async { - // print(selectedFolder) try { List fetchedEmails = await apiService .fetchEmailsFromFolder(widget.selectedFolder, widget.offset); @@ -134,7 +133,6 @@ class EmailPageState extends State { @override Widget build(BuildContext context) { - _fetchEmails(); return Scaffold( body: EmailListScreen( emails: emails, From 9297468f6fc086031d08a704283e79b8eeb69f1c Mon Sep 17 00:00:00 2001 From: juan Date: Thu, 8 May 2025 16:00:46 -0400 Subject: [PATCH 07/19] finished api calls for moving an email, cleaned, and made clearer logs for errors in api calls --- lib/api_service.dart | 65 +++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/lib/api_service.dart b/lib/api_service.dart index 75f21a8..b9ffdf8 100644 --- a/lib/api_service.dart +++ b/lib/api_service.dart @@ -18,9 +18,11 @@ import 'dart:js' as js; class ApiService { static String ip = ""; static String port = ""; - static List threadAttachments = []; + static List threadAttachments = + []; //holds attachments of the thread static String currFolder = ""; - static List currThread = []; + static List currThread = []; //holds the email ids of the thread + static String currThreadID = ""; //picked an email it prints the threadID Future> fetchEmailsFromFolder( String folder, int pagenitaion) async { @@ -31,7 +33,6 @@ class ApiService { 'offset': pagenitaion.toString(), }); var response = await http.get(url); - // print(response); List allEmails = []; if (response.statusCode == 200) { @@ -143,13 +144,52 @@ class ApiService { return content; } - Future moveEmail(String fromFolder, String uID, String toFolder) async { + Future> threadsInSerializable( + String thread_id) async { + // grab all of the emails in thread anyways, for the future it'll come in handy + var url = Uri.http('$ip:$port', 'get_thread_messages', {'id': thread_id}); + try { + var response = await http.get(url); + if (response.statusCode == 200) { + List json = jsonDecode(response.body); + List serializableMessages = []; + for (var mail in json) { + serializableMessages.add(SerializableMessage.fromJson(mail)); + } + return serializableMessages; + } else { + print( + "failed get request with status code ${response.statusCode}, and body ${response.body}"); + } + } catch (e) { + print("caught in threadInSerializable method error: $e"); + } + + return []; + } + + Future moveEmail( + //only moves the first email of the thread //or perhaps should do the last + String fromFolder, + String thread_id, + String toFolder) async { var url = Uri.http('$ip:$port', 'move_email'); + + List mailsInSerializable = + await this.threadsInSerializable(thread_id); + + if (mailsInSerializable.isEmpty) { + return false; + } + + SerializableMessage firstMail = mailsInSerializable[0]; + Map requestBody = { 'from': fromFolder, - 'uid': uID, + 'uid': firstMail.uid.toString(), 'to': toFolder, }; + try { var response = await http.post( url, @@ -162,10 +202,10 @@ class ApiService { print('response body ${response.body}'); return true; } else { - print('error '); + print('error ${response.statusCode} ${response.body}'); } } catch (e) { - print(e); + print("failed trying to post move_email, with error: $e"); } return false; } @@ -253,13 +293,6 @@ class ApiService { } Future logIn(String json) async { - // var url = Uri.https('') - // try{ - // String response = await http.post( - // url - // ); - // } - return false; } @@ -298,7 +331,6 @@ class ApiService { var response = await http.get(url); if (response.statusCode == 200) { var result = response.body; - // print(result); Map attachmentData = json.decode(result); AttachmentResponse data = AttachmentResponse.fromJson(attachmentData); print("data $data"); @@ -449,7 +481,8 @@ class _EmailViewState extends State { @override Widget build(BuildContext context) { - // print(currentContent); + // print("thread id ${widget.id}"); + ApiService.currThreadID = widget.id; return Scaffold( appBar: AppBar( title: Text(widget.name), From 7a1e735f1198eba3a2296535f39ddd8eb809777f Mon Sep 17 00:00:00 2001 From: juan Date: Mon, 12 May 2025 15:53:40 -0400 Subject: [PATCH 08/19] select list of which foilder to move your email --- lib/api_service.dart | 3 +- lib/augment.dart | 175 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 171 insertions(+), 7 deletions(-) diff --git a/lib/api_service.dart b/lib/api_service.dart index b9ffdf8..4525d32 100644 --- a/lib/api_service.dart +++ b/lib/api_service.dart @@ -46,6 +46,7 @@ class ApiService { } } } + currFolder = folder; return allEmails; } else { throw Exception('Failed to load threads'); @@ -159,7 +160,7 @@ class ApiService { return serializableMessages; } else { print( - "failed get request with status code ${response.statusCode}, and body ${response.body}"); + "failed get request with status code ${response.statusCode}, and body ${response.body}"); } } catch (e) { print("caught in threadInSerializable method error: $e"); diff --git a/lib/augment.dart b/lib/augment.dart index ebee03b..21c6770 100644 --- a/lib/augment.dart +++ b/lib/augment.dart @@ -1,7 +1,10 @@ +// import 'dart:ffi'; + import 'package:crab_ui/api_service.dart'; import 'package:crab_ui/attachmentDownload.dart'; import 'package:crab_ui/structs.dart'; import 'package:flutter/material.dart'; +import 'package:pdfrx/pdfrx.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'dart:html' as html; import 'dart:js' as js; @@ -88,6 +91,12 @@ class _DynamicClassesAugment extends State { onPressed: AugmentClasses.handleStop, child: Text('Stop'), ), + ElevatedButton( + onPressed: () { + AugmentClasses.handleMove(context); + }, + child: Text('Move'), + ), Spacer(), PopupMenuButton( onSelected: (String value) { @@ -212,8 +221,9 @@ class _DynamicClassesAugment extends State { } class AugmentClasses { - ApiService _apiService = ApiService(); static OverlayEntry? _overlayEntry; + static String? selectedFolder; // Manage selected folder at the class level + static void handleHome(BuildContext context) { Navigator.of(context).popUntil((route) => route.isFirst); } @@ -222,11 +232,165 @@ class AugmentClasses { print("reload"); } + Widget listOfFolders(BuildContext context) { + //list the emails and make some sort of selection box + return FutureBuilder>( + future: ApiService().fetchFolders(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } else if (snapshot.hasData) { + String? selectedFolder; // Declare the selected folder state + return StatefulBuilder( + builder: (context, setState) { + return ListView( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + children: snapshot.data!.map((folder) { + return RadioListTile( + title: Text(folder), + value: folder, + groupValue: selectedFolder, + onChanged: (String? value) { + setState(() { + selectedFolder = value; // Update the selected folder + }); + }, + ); + }).toList(), + ); + }, + ); + } else { + return const Center(child: Text('No folders found.')); + } + }, + ); + } + + static void handleMove(BuildContext context) async { + print("current folder: ${ApiService.currFolder}"); + final overlay = Overlay.of(context); + String? selectedFolder; // Variable to store the selected folder + + _overlayEntry = OverlayEntry( + builder: (context) => Stack( + children: [ + // Dimmed background + Container( + color: Colors.black54, + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + ), + // Focused content window + PointerInterceptor( + child: Center( + child: Material( + elevation: 8, + borderRadius: BorderRadius.circular(12), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400, + maxHeight: 500, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Move email from folder ${ApiService.currFolder} to:', + style: TextStyle(fontSize: 16), + ), + Divider(height: 1), + Expanded( + child: FutureBuilder>( + future: ApiService().fetchFolders(), + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState.waiting) { + return const Center( + child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center( + child: Text('Error: ${snapshot.error}')); + } else if (snapshot.hasData) { + return StatefulBuilder( + builder: (context, setState) { + return ListView( + shrinkWrap: true, + children: snapshot.data!.map((folder) { + return RadioListTile( + title: Text(folder), + value: folder, + groupValue: selectedFolder, + onChanged: (String? value) { + setState(() { + selectedFolder = value; // Update the selected folder + }); + }, + ); + }).toList(), + ); + }, + ); + } else { + return const Center( + child: Text('No folders found.')); + } + }, + ), + ), + Divider(height: 1), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () { + // Handle Accept button + if (selectedFolder != null) { + print("Selected folder: $selectedFolder"); + // Store the selected folder or perform any action + // ApiService.currFolder = selectedFolder!; + ApiService() + .moveEmail(ApiService.currFolder, ApiService.currThreadID, selectedFolder!); + _overlayEntry?.remove(); + } else { + print("No folder selected"); + } + }, + child: Text('Accept'), + ), + ElevatedButton( + onPressed: () { + // Handle Cancel button + _overlayEntry?.remove(); + }, + child: Text('Cancel'), + ), + ], + ), + ], + ), + ), + ), + ), + ), + ], + ), + ); + + if (_overlayEntry != null) { + overlay.insert(_overlayEntry!); + } + } + static void handleImages(BuildContext context) { + //rename to handle attachments print("Images button pressed"); final overlay = Overlay.of(context); - final renderBox = context.findRenderObject() as RenderBox; - final offset = renderBox.localToGlobal(Offset.zero); + // final renderBox = context.findRenderObject() as RenderBox; + // final offset = renderBox.localToGlobal(Offset.zero); _overlayEntry = OverlayEntry( builder: (context) => Stack( @@ -295,11 +459,10 @@ class AugmentClasses { static List _buildMenuItem(BuildContext context) { List listOfFiles = []; for (AttachmentResponse file in ApiService.threadAttachments) { - listOfFiles.add( - ListTile ( + listOfFiles.add(ListTile( leading: Icon(Icons.file_present), title: Text(file.name.toString()), - trailing: GestureDetector( + trailing: GestureDetector( child: Icon(Icons.download), onTap: () => Attachmentdownload().saveFile(file), ), From 9fff611ac099bb81bc80e55c84a7bc2301d4feae Mon Sep 17 00:00:00 2001 From: juan Date: Wed, 14 May 2025 21:52:21 -0400 Subject: [PATCH 09/19] scrapped html package and js, now using web --- lib/api_service.dart | 246 +++++++++++++++++++----------------- lib/attachmentDownload.dart | 1 + lib/augment.dart | 65 +++++----- 3 files changed, 167 insertions(+), 145 deletions(-) diff --git a/lib/api_service.dart b/lib/api_service.dart index 4525d32..cc2c719 100644 --- a/lib/api_service.dart +++ b/lib/api_service.dart @@ -12,8 +12,10 @@ import 'package:http/http.dart' as http; import 'dart:convert'; import 'dart:ui_web' as ui; import 'augment.dart'; -import 'dart:html' as html; -import 'dart:js' as js; +// import 'dart:html' as html; +// import 'dart:js' as js; +import 'package:web/web.dart' as web; +import 'dart:js_interop' as js; class ApiService { static String ip = ""; @@ -343,76 +345,77 @@ class ApiService { return AttachmentResponse(name: "error", data: Uint8List(0)); } - Future>> getMarkerPosition() async { - //this is so we can put a widget right below each email, but the way how the email content is generated - //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 + //TODO: MOVE THIS INTO WEB +// Future>> getMarkerPosition() async { +// //this is so we can put a widget right below each email, but the way how the email content is generated +// //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"); - // 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 - } -})(); -'''; +// print("marker 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]); +// 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"); +// 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 parsedResult = jsonDecode(result); - var positions = List>.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); - } +// // Parse the JSON string returned by JavaScript into a Dart list of maps +// final List parsedResult = jsonDecode(result); +// var positions = List>.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 []; - } +// return []; +// } } class EmailView extends StatefulWidget { @@ -455,10 +458,12 @@ class _EmailViewState extends State { @override void 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}"; _registerViewFactory(currentContent); - _markerPositionsFuture = ApiService().getMarkerPosition(); + // _markerPositionsFuture = ApiService().getMarkerPosition(); } void _registerViewFactory(String currentContent) { @@ -466,11 +471,20 @@ class _EmailViewState extends State { viewTypeId = 'iframe-${DateTime.now().millisecondsSinceEpoch}'; ui.platformViewRegistry.registerViewFactory( viewTypeId, - (int viewId) => html.IFrameElement() - ..width = '100%' - ..height = '100%' - ..srcdoc = currentContent - ..style.border = 'none'); + (int viewId) => web.HTMLDivElement() + ..id = 'new-web' + ..innerHTML = currentContent as js.JSAny); + + // 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 { //

Welcome to My Website

//

This is a simple HTML page.

//

What is HTML?

- //

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).

+ //

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).

//

Here's a simple list:

//
    //
  • HTML elements are the building blocks of HTML pages
  • @@ -562,48 +576,48 @@ class _EmailViewState extends State { ), // Overlay widgets dynamically based on marker positions - FutureBuilder>>( - 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(), - ); - } + // FutureBuilder>>( + // 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 - }, - ), + // return SizedBox.shrink(); // No markers found + // }, + // ), // Red widget overlay // Positioned( // left: 8, // Adjust based on your desired position diff --git a/lib/attachmentDownload.dart b/lib/attachmentDownload.dart index 4fc4639..63364ba 100644 --- a/lib/attachmentDownload.dart +++ b/lib/attachmentDownload.dart @@ -1,4 +1,5 @@ import 'dart:html' as html; +import 'package:web/web.dart' as web; import 'dart:io'; import 'structs.dart'; import 'package:file_saver/file_saver.dart'; diff --git a/lib/augment.dart b/lib/augment.dart index 21c6770..b957740 100644 --- a/lib/augment.dart +++ b/lib/augment.dart @@ -6,8 +6,9 @@ import 'package:crab_ui/structs.dart'; import 'package:flutter/material.dart'; import 'package:pdfrx/pdfrx.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; -import 'dart:html' as html; -import 'dart:js' as js; +// import 'dart:html' as html; +// import 'dart:js' as js; +import 'package:web/web.dart' as web; import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'attachmentWidget.dart'; @@ -326,7 +327,8 @@ class AugmentClasses { groupValue: selectedFolder, onChanged: (String? value) { setState(() { - selectedFolder = value; // Update the selected folder + selectedFolder = + value; // Update the selected folder }); }, ); @@ -352,8 +354,8 @@ class AugmentClasses { print("Selected folder: $selectedFolder"); // Store the selected folder or perform any action // ApiService.currFolder = selectedFolder!; - ApiService() - .moveEmail(ApiService.currFolder, ApiService.currThreadID, selectedFolder!); + ApiService().moveEmail(ApiService.currFolder, + ApiService.currThreadID, selectedFolder!); _overlayEntry?.remove(); } else { print("No folder selected"); @@ -512,7 +514,7 @@ class AugmentClasses { 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) {} @@ -520,7 +522,7 @@ class AugmentClasses { static Future JumpButton(BuildContext context) async { // FocusNode textFieldFocusNode = FocusNode(); - AugmentClasses.disableIframePointerEvents(); + // AugmentClasses.disableIframePointerEvents(); await showDialog( barrierDismissible: true, // barrierColor: Colors.yellow, @@ -602,7 +604,7 @@ class AugmentClasses { ], ), ).then((_) { - AugmentClasses.enableIframePointerEvents(); + // AugmentClasses.enableIframePointerEvents(); }); } @@ -612,7 +614,7 @@ class AugmentClasses { bool blankLines = false; bool numbering = false; bool statementSignatures = false; - AugmentClasses.disableIframePointerEvents(); + // AugmentClasses.disableIframePointerEvents(); await showDialog( context: context, builder: (context) => Container( @@ -723,7 +725,7 @@ class AugmentClasses { ElevatedButton(onPressed: () {}, child: Text('OK')), ElevatedButton( onPressed: () { - AugmentClasses.disableIframePointerEvents(); + // AugmentClasses.disableIframePointerEvents(); Navigator.of(context).pop(); }, child: Text('Cancel')), @@ -737,7 +739,7 @@ class AugmentClasses { ), ), )).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

    tags that contain these //words and highlight, then when zoom, you just jump to that paragraph - AugmentClasses.disableIframePointerEvents(); + // AugmentClasses.disableIframePointerEvents(); await showDialog( context: context, builder: (context) => Container( @@ -775,22 +777,27 @@ class AugmentClasses { ))))); } - static void disableIframePointerEvents() { - //pretty sure these dont work - final iframes = html.document.getElementsByTagName('iframe'); - for (var iframe in iframes) { - if (iframe is html.Element) { - iframe.style.pointerEvents = 'none'; // Disable pointer events - } - } - } + // 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'); - for (var iframe in iframes) { - if (iframe is html.Element) { - iframe.style.pointerEvents = 'auto'; // Re-enable pointer events - } - } - } + // 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 + // } + // } + // } } From 511f6948bb51c39f9655c0fb277dc3bc76d28ebe Mon Sep 17 00:00:00 2001 From: juan Date: Sat, 17 May 2025 23:11:52 -0400 Subject: [PATCH 10/19] clean 1 --- lib/serialize.dart | 85 -------------- pubspec.lock | 198 ++++++++++++++++++++++++++++++-- pubspec.yaml | 1 + web/favicon.png:Zone.Identifier | 3 - 4 files changed, 188 insertions(+), 99 deletions(-) delete mode 100644 lib/serialize.dart delete mode 100644 web/favicon.png:Zone.Identifier diff --git a/lib/serialize.dart b/lib/serialize.dart deleted file mode 100644 index 4ba21f1..0000000 --- a/lib/serialize.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'package:flutter/material.dart'; -import 'api_service.dart'; -import 'structs.dart'; - -class SerializableMessageListScreen extends StatefulWidget { - @override - _SerializableMessageListScreenState createState() => _SerializableMessageListScreenState(); -} - -class _SerializableMessageListScreenState extends State { - List? messages; - bool isLoading = true; - bool hasError = false; - - final ApiService apiService = ApiService(); - - @override - void initState() { - super.initState(); - _fetchMessages(); - } - - Future _fetchMessages() async { - try { - List fetchedMessages = await apiService.sonicSearch("INBOX", 10, 0, "searchQuery"); - setState(() { - messages = fetchedMessages; - isLoading = false; - }); - } catch (e) { - setState(() { - hasError = true; - isLoading = false; - }); - } - } - - @override - Widget build(BuildContext context) { - if (isLoading) { - return Center(child: CircularProgressIndicator()); - } - - if (hasError) { - return Center(child: Text("Error fetching messages.")); - } - - if (messages == null || messages!.isEmpty) { - return Center(child: Text("No messages found.")); - } - - return ListView.separated( - itemCount: messages!.length, - itemBuilder: (context, index) { - final message = messages![index]; - return ListTile( - title: Text(message.name, style: TextStyle(fontWeight: FontWeight.bold)), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [Text(message.subject)], - ), - trailing: Text(message.date), - onTap: () async { - String emailContent = await apiService.fetchEmailContent([message.id], message.list); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => EmailView( - emailContent: emailContent, - from: message.from, - name: message.name, - to: message.to.toString(), - subject: message.subject, - date: message.date, - id: message.id, - ), - ), - ); - }, - ); - }, - separatorBuilder: (context, index) => Divider(), - ); - } -} diff --git a/pubspec.lock b/pubspec.lock index 2454c65..f4b7708 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.0" + asn1lib: + dependency: transitive + description: + name: asn1lib + sha256: "4bae5ae63e6d6dd17c4aac8086f3dec26c0236f6a0f03416c6c19d830c367cf5" + url: "https://pub.dev" + source: hosted + version: "1.5.8" async: dependency: transitive description: @@ -97,14 +105,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" crypto: dependency: transitive description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.6" csslib: dependency: transitive description: @@ -121,6 +137,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + dio: + dependency: transitive + description: + name: dio + sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" + url: "https://pub.dev" + source: hosted + version: "5.8.0+1" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + encrypt: + dependency: "direct main" + description: + name: encrypt + sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" + url: "https://pub.dev" + source: hosted + version: "5.0.3" english_words: dependency: "direct main" description: @@ -141,10 +181,10 @@ packages: dependency: transitive description: name: ffi - sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" file: dependency: transitive description: @@ -153,6 +193,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + file_saver: + dependency: "direct main" + description: + name: file_saver + sha256: "017a127de686af2d2fbbd64afea97052d95f2a0f87d19d25b87e097407bf9c1e" + url: "https://pub.dev" + source: hosted + version: "0.2.14" fixnum: dependency: transitive description: @@ -368,6 +416,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + intl: + dependency: "direct main" + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" js: dependency: transitive description: @@ -464,6 +520,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.0" + mime: + dependency: "direct main" + description: + name: mime + sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" + url: "https://pub.dev" + source: hosted + version: "1.0.6" nested: dependency: transitive description: @@ -500,10 +564,10 @@ packages: dependency: transitive description: name: path_provider - sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" path_provider_android: dependency: transitive description: @@ -544,6 +608,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + pdfrx: + dependency: "direct main" + description: + name: pdfrx + sha256: "29c7b03d27d647c80da8cc08bd1256c74df90e5640fdd676646e4bd04f90553a" + url: "https://pub.dev" + source: hosted + version: "1.0.94" petitparser: dependency: transitive description: @@ -552,6 +624,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.2" + photo_view: + dependency: "direct main" + description: + name: photo_view + sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e" + url: "https://pub.dev" + source: hosted + version: "0.15.0" platform: dependency: transitive description: @@ -568,6 +648,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + pointer_interceptor: + dependency: "direct main" + description: + name: pointer_interceptor + sha256: "57210410680379aea8b1b7ed6ae0c3ad349bfd56fe845b8ea934a53344b9d523" + url: "https://pub.dev" + source: hosted + version: "0.10.1+2" + pointer_interceptor_ios: + dependency: transitive + description: + name: pointer_interceptor_ios + sha256: a6906772b3205b42c44614fcea28f818b1e5fdad73a4ca742a7bd49818d9c917 + url: "https://pub.dev" + source: hosted + version: "0.10.1" + pointer_interceptor_platform_interface: + dependency: transitive + description: + name: pointer_interceptor_platform_interface + sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506" + url: "https://pub.dev" + source: hosted + version: "0.10.0+1" + pointer_interceptor_web: + dependency: transitive + description: + name: pointer_interceptor_web + sha256: "7a7087782110f8c1827170660b09f8aa893e0e9a61431dbbe2ac3fc482e8c044" + url: "https://pub.dev" + source: hosted + version: "0.10.2+1" + pointycastle: + dependency: "direct main" + description: + name: pointycastle + sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" + url: "https://pub.dev" + source: hosted + version: "3.9.1" provider: dependency: "direct main" description: @@ -592,6 +712,62 @@ packages: url: "https://pub.dev" source: hosted version: "0.27.7" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "95f9997ca1fb9799d494d0cb2a780fd7be075818d59f00c43832ed112b158a82" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e + url: "https://pub.dev" + source: hosted + version: "2.4.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" sky_engine: dependency: transitive description: flutter @@ -697,10 +873,10 @@ packages: dependency: transitive description: name: url_launcher - sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_android: dependency: transitive description: @@ -886,13 +1062,13 @@ packages: source: hosted version: "0.2.1" web: - dependency: transitive + dependency: "direct main" description: name: web - sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.1.1" webview_flutter: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3f94c16..8de6880 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -27,6 +27,7 @@ dependencies: intl: ^0.19.0 pdfrx: ^1.0.94 photo_view: ^0.15.0 + web: ^1.1.1 dev_dependencies: flutter_test: diff --git a/web/favicon.png:Zone.Identifier b/web/favicon.png:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/web/favicon.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip From 7550fdca65bd85c52b773487371553bca0f3325b Mon Sep 17 00:00:00 2001 From: juan Date: Sat, 17 May 2025 23:27:46 -0400 Subject: [PATCH 11/19] delete android --- .gitignore | 118 +++++++++++------- android/.gitignore | 13 -- android/.gitignore:Zone.Identifier | 3 - android/app/build.gradle | 58 --------- android/app/src/debug/AndroidManifest.xml | 7 -- android/app/src/main/AndroidManifest.xml | 45 ------- .../com/example/crab_ui/MainActivity.kt | 5 - .../res/drawable-v21/launch_background.xml | 12 -- .../launch_background.xml:Zone.Identifier | 3 - .../main/res/drawable/launch_background.xml | 12 -- .../launch_background.xml:Zone.Identifier | 3 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 544 -> 0 bytes .../ic_launcher.png:Zone.Identifier | 3 - .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 442 -> 0 bytes .../ic_launcher.png:Zone.Identifier | 3 - .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 721 -> 0 bytes .../ic_launcher.png:Zone.Identifier | 3 - .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1031 -> 0 bytes .../ic_launcher.png:Zone.Identifier | 3 - .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 1443 -> 0 bytes .../ic_launcher.png:Zone.Identifier | 3 - .../app/src/main/res/values-night/styles.xml | 18 --- .../values-night/styles.xml:Zone.Identifier | 3 - android/app/src/main/res/values/styles.xml | 18 --- .../res/values/styles.xml:Zone.Identifier | 3 - android/app/src/profile/AndroidManifest.xml | 7 -- android/build.gradle | 18 --- android/gradle.properties | 3 - .../gradle/wrapper/gradle-wrapper.properties | 5 - android/settings.gradle | 25 ---- 30 files changed, 75 insertions(+), 319 deletions(-) delete mode 100644 android/.gitignore delete mode 100644 android/.gitignore:Zone.Identifier delete mode 100644 android/app/build.gradle delete mode 100644 android/app/src/debug/AndroidManifest.xml delete mode 100644 android/app/src/main/AndroidManifest.xml delete mode 100644 android/app/src/main/kotlin/com/example/crab_ui/MainActivity.kt delete mode 100644 android/app/src/main/res/drawable-v21/launch_background.xml delete mode 100644 android/app/src/main/res/drawable-v21/launch_background.xml:Zone.Identifier delete mode 100644 android/app/src/main/res/drawable/launch_background.xml delete mode 100644 android/app/src/main/res/drawable/launch_background.xml:Zone.Identifier delete mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png:Zone.Identifier delete mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png:Zone.Identifier delete mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:Zone.Identifier delete mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:Zone.Identifier delete mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:Zone.Identifier delete mode 100644 android/app/src/main/res/values-night/styles.xml delete mode 100644 android/app/src/main/res/values-night/styles.xml:Zone.Identifier delete mode 100644 android/app/src/main/res/values/styles.xml delete mode 100644 android/app/src/main/res/values/styles.xml:Zone.Identifier delete mode 100644 android/app/src/profile/AndroidManifest.xml delete mode 100644 android/build.gradle delete mode 100644 android/gradle.properties delete mode 100644 android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 android/settings.gradle diff --git a/.gitignore b/.gitignore index 29a3a50..02e929b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,43 +1,75 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ +.VSCodeCounter +*:Zone.Identifier +.packages +*.lock +*.tmp +*.temp +*.bak +*.old + + + + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +.vscode/ +/linux +/macos +/windows + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +# /android/app/debug +# /android/app/profile +# /android/app/release +# /android + + +# build +# android/.gradle/ +# android/local.properties +ios/Flutter/Generated.xcconfig +ios/Flutter/App.framework +ios/Flutter/Flutter.framework +ios/Flutter/Flutter.podspec +ios/.symlinks/ +ios/Pods/ +ios/.generated/ +macos/Flutter/GeneratedPluginRegistrant.swift +macos/Pods/ +macos/.symlinks/ +linux/flutter/ +windows/flutter/ diff --git a/android/.gitignore b/android/.gitignore deleted file mode 100644 index 6f56801..0000000 --- a/android/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java - -# Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app -key.properties -**/*.keystore -**/*.jks diff --git a/android/.gitignore:Zone.Identifier b/android/.gitignore:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/android/.gitignore:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/android/app/build.gradle b/android/app/build.gradle deleted file mode 100644 index 42bb5ec..0000000 --- a/android/app/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file("local.properties") -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader("UTF-8") { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty("flutter.versionCode") -if (flutterVersionCode == null) { - flutterVersionCode = "1" -} - -def flutterVersionName = localProperties.getProperty("flutter.versionName") -if (flutterVersionName == null) { - flutterVersionName = "1.0" -} - -android { - namespace = "com.example.crab_ui" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.example.crab_ui" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutterVersionCode.toInteger() - versionName = flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.debug - } - } -} - -flutter { - source = "../.." -} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 399f698..0000000 --- a/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 080a94f..0000000 --- a/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/android/app/src/main/kotlin/com/example/crab_ui/MainActivity.kt b/android/app/src/main/kotlin/com/example/crab_ui/MainActivity.kt deleted file mode 100644 index 3b55c4c..0000000 --- a/android/app/src/main/kotlin/com/example/crab_ui/MainActivity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.example.crab_ui - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index f74085f..0000000 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml:Zone.Identifier b/android/app/src/main/res/drawable-v21/launch_background.xml:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/android/app/src/main/res/drawable-v21/launch_background.xml:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f..0000000 --- a/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/android/app/src/main/res/drawable/launch_background.xml:Zone.Identifier b/android/app/src/main/res/drawable/launch_background.xml:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/android/app/src/main/res/drawable/launch_background.xml:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4b7b0906d62b1847e87f15cdcacf6a4f29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:Zone.Identifier b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b79bb8a35cc66c3c1fd44f5a5526c1b78be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:Zone.Identifier b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d34e7a88e3f88bea192c3a370d44689c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:Zone.Identifier b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372eebdb28e45604e46eeda8dd24651419bc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:Zone.Identifier b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml deleted file mode 100644 index 06952be..0000000 --- a/android/app/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/android/app/src/main/res/values-night/styles.xml:Zone.Identifier b/android/app/src/main/res/values-night/styles.xml:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/android/app/src/main/res/values-night/styles.xml:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml deleted file mode 100644 index cb1ef88..0000000 --- a/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/android/app/src/main/res/values/styles.xml:Zone.Identifier b/android/app/src/main/res/values/styles.xml:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/android/app/src/main/res/values/styles.xml:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f698..0000000 --- a/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/android/build.gradle b/android/build.gradle deleted file mode 100644 index d2ffbff..0000000 --- a/android/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = "../build" -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/android/gradle.properties b/android/gradle.properties deleted file mode 100644 index 3b5b324..0000000 --- a/android/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true -android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index e1ca574..0000000 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip diff --git a/android/settings.gradle b/android/settings.gradle deleted file mode 100644 index 536165d..0000000 --- a/android/settings.gradle +++ /dev/null @@ -1,25 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false - id "org.jetbrains.kotlin.android" version "1.7.10" apply false -} - -include ":app" From c9c239767a4a41f8bea5c3701995c25260403a48 Mon Sep 17 00:00:00 2001 From: juan Date: Sun, 18 May 2025 01:40:46 -0400 Subject: [PATCH 12/19] remove zone identifiers for windows compatibility --- assets/back.png:Zone.Identifier | 3 --- assets/communications.png:Zone.Identifier | 3 --- assets/contact-book.png:Zone.Identifier | 3 --- assets/email.png:Zone.Identifier | 3 --- ios/.gitignore:Zone.Identifier | 3 --- ios/Flutter/AppFrameworkInfo.plist:Zone.Identifier | 3 --- ios/Flutter/Debug.xcconfig:Zone.Identifier | 3 --- ios/Flutter/Release.xcconfig:Zone.Identifier | 3 --- .../contents.xcworkspacedata:Zone.Identifier | 3 --- .../xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier | 3 --- .../xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier | 3 --- .../xcshareddata/xcschemes/Runner.xcscheme:Zone.Identifier | 3 --- .../contents.xcworkspacedata:Zone.Identifier | 3 --- .../xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier | 3 --- .../xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier | 3 --- ios/Runner/AppDelegate.swift:Zone.Identifier | 3 --- .../AppIcon.appiconset/Contents.json:Zone.Identifier | 3 --- .../LaunchImage.imageset/Contents.json:Zone.Identifier | 3 --- .../LaunchImage.imageset/README.md:Zone.Identifier | 3 --- ios/Runner/Base.lproj/LaunchScreen.storyboard:Zone.Identifier | 3 --- ios/Runner/Base.lproj/Main.storyboard:Zone.Identifier | 3 --- ios/Runner/Runner-Bridging-Header.h:Zone.Identifier | 3 --- linux/.gitignore:Zone.Identifier | 3 --- linux/flutter/CMakeLists.txt:Zone.Identifier | 3 --- linux/main.cc:Zone.Identifier | 3 --- linux/my_application.h:Zone.Identifier | 3 --- macos/.gitignore:Zone.Identifier | 3 --- macos/Flutter/Flutter-Debug.xcconfig:Zone.Identifier | 3 --- macos/Flutter/Flutter-Release.xcconfig:Zone.Identifier | 3 --- .../xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier | 3 --- .../contents.xcworkspacedata:Zone.Identifier | 3 --- .../xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier | 3 --- macos/Runner/AppDelegate.swift:Zone.Identifier | 3 --- .../AppIcon.appiconset/Contents.json:Zone.Identifier | 3 --- macos/Runner/Base.lproj/MainMenu.xib:Zone.Identifier | 3 --- macos/Runner/Configs/Debug.xcconfig:Zone.Identifier | 3 --- macos/Runner/Configs/Release.xcconfig:Zone.Identifier | 3 --- macos/Runner/Configs/Warnings.xcconfig:Zone.Identifier | 3 --- macos/Runner/DebugProfile.entitlements:Zone.Identifier | 3 --- macos/Runner/Info.plist:Zone.Identifier | 3 --- macos/Runner/MainFlutterWindow.swift:Zone.Identifier | 3 --- macos/Runner/Release.entitlements:Zone.Identifier | 3 --- web/icons/Icon-192.png:Zone.Identifier | 3 --- web/icons/Icon-512.png:Zone.Identifier | 3 --- windows/.gitignore:Zone.Identifier | 3 --- windows/flutter/CMakeLists.txt:Zone.Identifier | 3 --- windows/runner/CMakeLists.txt:Zone.Identifier | 3 --- windows/runner/flutter_window.cpp:Zone.Identifier | 3 --- windows/runner/flutter_window.h:Zone.Identifier | 3 --- windows/runner/resource.h:Zone.Identifier | 3 --- windows/runner/runner.exe.manifest:Zone.Identifier | 3 --- windows/runner/utils.cpp:Zone.Identifier | 3 --- windows/runner/utils.h:Zone.Identifier | 3 --- windows/runner/win32_window.cpp:Zone.Identifier | 3 --- windows/runner/win32_window.h:Zone.Identifier | 3 --- 55 files changed, 165 deletions(-) delete mode 100644 assets/back.png:Zone.Identifier delete mode 100644 assets/communications.png:Zone.Identifier delete mode 100644 assets/contact-book.png:Zone.Identifier delete mode 100644 assets/email.png:Zone.Identifier delete mode 100644 ios/.gitignore:Zone.Identifier delete mode 100644 ios/Flutter/AppFrameworkInfo.plist:Zone.Identifier delete mode 100644 ios/Flutter/Debug.xcconfig:Zone.Identifier delete mode 100644 ios/Flutter/Release.xcconfig:Zone.Identifier delete mode 100644 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:Zone.Identifier delete mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier delete mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier delete mode 100644 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:Zone.Identifier delete mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata:Zone.Identifier delete mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier delete mode 100644 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier delete mode 100644 ios/Runner/AppDelegate.swift:Zone.Identifier delete mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:Zone.Identifier delete mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:Zone.Identifier delete mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:Zone.Identifier delete mode 100644 ios/Runner/Base.lproj/LaunchScreen.storyboard:Zone.Identifier delete mode 100644 ios/Runner/Base.lproj/Main.storyboard:Zone.Identifier delete mode 100644 ios/Runner/Runner-Bridging-Header.h:Zone.Identifier delete mode 100644 linux/.gitignore:Zone.Identifier delete mode 100644 linux/flutter/CMakeLists.txt:Zone.Identifier delete mode 100644 linux/main.cc:Zone.Identifier delete mode 100644 linux/my_application.h:Zone.Identifier delete mode 100644 macos/.gitignore:Zone.Identifier delete mode 100644 macos/Flutter/Flutter-Debug.xcconfig:Zone.Identifier delete mode 100644 macos/Flutter/Flutter-Release.xcconfig:Zone.Identifier delete mode 100644 macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier delete mode 100644 macos/Runner.xcworkspace/contents.xcworkspacedata:Zone.Identifier delete mode 100644 macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier delete mode 100644 macos/Runner/AppDelegate.swift:Zone.Identifier delete mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:Zone.Identifier delete mode 100644 macos/Runner/Base.lproj/MainMenu.xib:Zone.Identifier delete mode 100644 macos/Runner/Configs/Debug.xcconfig:Zone.Identifier delete mode 100644 macos/Runner/Configs/Release.xcconfig:Zone.Identifier delete mode 100644 macos/Runner/Configs/Warnings.xcconfig:Zone.Identifier delete mode 100644 macos/Runner/DebugProfile.entitlements:Zone.Identifier delete mode 100644 macos/Runner/Info.plist:Zone.Identifier delete mode 100644 macos/Runner/MainFlutterWindow.swift:Zone.Identifier delete mode 100644 macos/Runner/Release.entitlements:Zone.Identifier delete mode 100644 web/icons/Icon-192.png:Zone.Identifier delete mode 100644 web/icons/Icon-512.png:Zone.Identifier delete mode 100644 windows/.gitignore:Zone.Identifier delete mode 100644 windows/flutter/CMakeLists.txt:Zone.Identifier delete mode 100644 windows/runner/CMakeLists.txt:Zone.Identifier delete mode 100644 windows/runner/flutter_window.cpp:Zone.Identifier delete mode 100644 windows/runner/flutter_window.h:Zone.Identifier delete mode 100644 windows/runner/resource.h:Zone.Identifier delete mode 100644 windows/runner/runner.exe.manifest:Zone.Identifier delete mode 100644 windows/runner/utils.cpp:Zone.Identifier delete mode 100644 windows/runner/utils.h:Zone.Identifier delete mode 100644 windows/runner/win32_window.cpp:Zone.Identifier delete mode 100644 windows/runner/win32_window.h:Zone.Identifier diff --git a/assets/back.png:Zone.Identifier b/assets/back.png:Zone.Identifier deleted file mode 100644 index 1ebf061..0000000 --- a/assets/back.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -HostUrl=https://onlinepngtools.com/ diff --git a/assets/communications.png:Zone.Identifier b/assets/communications.png:Zone.Identifier deleted file mode 100644 index 1ebf061..0000000 --- a/assets/communications.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -HostUrl=https://onlinepngtools.com/ diff --git a/assets/contact-book.png:Zone.Identifier b/assets/contact-book.png:Zone.Identifier deleted file mode 100644 index 1ebf061..0000000 --- a/assets/contact-book.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -HostUrl=https://onlinepngtools.com/ diff --git a/assets/email.png:Zone.Identifier b/assets/email.png:Zone.Identifier deleted file mode 100644 index 1ebf061..0000000 --- a/assets/email.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -HostUrl=https://onlinepngtools.com/ diff --git a/ios/.gitignore:Zone.Identifier b/ios/.gitignore:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/.gitignore:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Flutter/AppFrameworkInfo.plist:Zone.Identifier b/ios/Flutter/AppFrameworkInfo.plist:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Flutter/AppFrameworkInfo.plist:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Flutter/Debug.xcconfig:Zone.Identifier b/ios/Flutter/Debug.xcconfig:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Flutter/Debug.xcconfig:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Flutter/Release.xcconfig:Zone.Identifier b/ios/Flutter/Release.xcconfig:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Flutter/Release.xcconfig:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:Zone.Identifier b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:Zone.Identifier b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata:Zone.Identifier b/ios/Runner.xcworkspace/contents.xcworkspacedata:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner/AppDelegate.swift:Zone.Identifier b/ios/Runner/AppDelegate.swift:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner/AppDelegate.swift:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:Zone.Identifier b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:Zone.Identifier b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:Zone.Identifier b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard:Zone.Identifier b/ios/Runner/Base.lproj/LaunchScreen.storyboard:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner/Base.lproj/LaunchScreen.storyboard:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner/Base.lproj/Main.storyboard:Zone.Identifier b/ios/Runner/Base.lproj/Main.storyboard:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner/Base.lproj/Main.storyboard:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/ios/Runner/Runner-Bridging-Header.h:Zone.Identifier b/ios/Runner/Runner-Bridging-Header.h:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/ios/Runner/Runner-Bridging-Header.h:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/linux/.gitignore:Zone.Identifier b/linux/.gitignore:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/linux/.gitignore:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/linux/flutter/CMakeLists.txt:Zone.Identifier b/linux/flutter/CMakeLists.txt:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/linux/flutter/CMakeLists.txt:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/linux/main.cc:Zone.Identifier b/linux/main.cc:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/linux/main.cc:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/linux/my_application.h:Zone.Identifier b/linux/my_application.h:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/linux/my_application.h:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/.gitignore:Zone.Identifier b/macos/.gitignore:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/.gitignore:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Flutter/Flutter-Debug.xcconfig:Zone.Identifier b/macos/Flutter/Flutter-Debug.xcconfig:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Flutter/Flutter-Debug.xcconfig:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Flutter/Flutter-Release.xcconfig:Zone.Identifier b/macos/Flutter/Flutter-Release.xcconfig:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Flutter/Flutter-Release.xcconfig:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata:Zone.Identifier b/macos/Runner.xcworkspace/contents.xcworkspacedata:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner.xcworkspace/contents.xcworkspacedata:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/AppDelegate.swift:Zone.Identifier b/macos/Runner/AppDelegate.swift:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/AppDelegate.swift:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:Zone.Identifier b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/Base.lproj/MainMenu.xib:Zone.Identifier b/macos/Runner/Base.lproj/MainMenu.xib:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/Base.lproj/MainMenu.xib:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/Configs/Debug.xcconfig:Zone.Identifier b/macos/Runner/Configs/Debug.xcconfig:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/Configs/Debug.xcconfig:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/Configs/Release.xcconfig:Zone.Identifier b/macos/Runner/Configs/Release.xcconfig:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/Configs/Release.xcconfig:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/Configs/Warnings.xcconfig:Zone.Identifier b/macos/Runner/Configs/Warnings.xcconfig:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/Configs/Warnings.xcconfig:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/DebugProfile.entitlements:Zone.Identifier b/macos/Runner/DebugProfile.entitlements:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/DebugProfile.entitlements:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/Info.plist:Zone.Identifier b/macos/Runner/Info.plist:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/Info.plist:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/MainFlutterWindow.swift:Zone.Identifier b/macos/Runner/MainFlutterWindow.swift:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/MainFlutterWindow.swift:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/macos/Runner/Release.entitlements:Zone.Identifier b/macos/Runner/Release.entitlements:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/macos/Runner/Release.entitlements:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/web/icons/Icon-192.png:Zone.Identifier b/web/icons/Icon-192.png:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/web/icons/Icon-192.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/web/icons/Icon-512.png:Zone.Identifier b/web/icons/Icon-512.png:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/web/icons/Icon-512.png:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/.gitignore:Zone.Identifier b/windows/.gitignore:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/.gitignore:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/flutter/CMakeLists.txt:Zone.Identifier b/windows/flutter/CMakeLists.txt:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/flutter/CMakeLists.txt:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/runner/CMakeLists.txt:Zone.Identifier b/windows/runner/CMakeLists.txt:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/runner/CMakeLists.txt:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/runner/flutter_window.cpp:Zone.Identifier b/windows/runner/flutter_window.cpp:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/runner/flutter_window.cpp:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/runner/flutter_window.h:Zone.Identifier b/windows/runner/flutter_window.h:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/runner/flutter_window.h:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/runner/resource.h:Zone.Identifier b/windows/runner/resource.h:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/runner/resource.h:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/runner/runner.exe.manifest:Zone.Identifier b/windows/runner/runner.exe.manifest:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/runner/runner.exe.manifest:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/runner/utils.cpp:Zone.Identifier b/windows/runner/utils.cpp:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/runner/utils.cpp:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/runner/utils.h:Zone.Identifier b/windows/runner/utils.h:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/runner/utils.h:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/runner/win32_window.cpp:Zone.Identifier b/windows/runner/win32_window.cpp:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/runner/win32_window.cpp:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip diff --git a/windows/runner/win32_window.h:Zone.Identifier b/windows/runner/win32_window.h:Zone.Identifier deleted file mode 100644 index b0a0755..0000000 --- a/windows/runner/win32_window.h:Zone.Identifier +++ /dev/null @@ -1,3 +0,0 @@ -[ZoneTransfer] -ZoneId=3 -ReferrerUrl=C:\Users\juana\Flutter\flutter_windows_3.22.2-stable.zip From c77eb114b7b888c5487ab4efaf0304853ac12168 Mon Sep 17 00:00:00 2001 From: juan Date: Sun, 18 May 2025 20:51:21 -0400 Subject: [PATCH 13/19] added more member variables to EmailView so i can render html differently, and also changed the way how html is being handled and call CollapsableEmails --- lib/api_service.dart | 74 +++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/lib/api_service.dart b/lib/api_service.dart index cc2c719..a9b6b20 100644 --- a/lib/api_service.dart +++ b/lib/api_service.dart @@ -5,6 +5,8 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:pointer_interceptor/pointer_interceptor.dart'; +import 'collapsableEmails.dart'; + import 'structs.dart'; import 'package:flutter/material.dart'; @@ -111,11 +113,13 @@ class ApiService { } //returns the html for the email, it gets used in emailView - Future fetchEmailContent( + Future> fetchEmailContent( List IDsString, String emailFolder) async { String content = r""" """; + List HTMLofThread = []; threadAttachments = []; + int counter = 0; try { //attaches email after email from a thread @@ -124,7 +128,9 @@ class ApiService { var response = await http.get(url); currThread.add(id); if (response.statusCode == 200) { + counter += 1; content += response.body; + HTMLofThread.add(response.body); try { List attachments = await getAttachmentsInfo(emailFolder, id); @@ -138,13 +144,14 @@ class ApiService { } content += """

    """; - content += "
    "; + content += "

    end of email

    "; } } } catch (e) { print('_getEmailContent caught error: $e'); } - return content; + // return content; + return HTMLofThread; } Future> threadsInSerializable( @@ -419,13 +426,14 @@ class ApiService { } class EmailView extends StatefulWidget { - final String emailContent; + final List emailContent; final String from; final String name; final String to; final String subject; final String date; final String id; + final List messages; const EmailView({ Key? key, @@ -436,6 +444,7 @@ class EmailView extends StatefulWidget { required this.subject, required this.date, required this.id, + required this.messages, }) : super(key: key); @override _EmailViewState createState() => _EmailViewState(); @@ -445,7 +454,7 @@ class _EmailViewState extends State { //html css rendering thing late Key iframeKey; late String currentContent; - late String viewTypeId; + late String viewTypeId; //make this a list too??? Future>>? _markerPositionsFuture; // TextEditingController _jumpController = TextEditingController(); final hardcodedMarkers = [ @@ -458,33 +467,37 @@ class _EmailViewState extends State { @override void initState() { super.initState(); - String currentContent = widget + List 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); // _markerPositionsFuture = ApiService().getMarkerPosition(); } - void _registerViewFactory(String currentContent) { - setState(() { + void _registerViewFactory(List currentContent) { + setState(() { //update to do item per item + // each item to have itsviewtype ID + // is this necessarey here?? + + //could just move to collapsable + + + viewTypeId = 'iframe-${DateTime.now().millisecondsSinceEpoch}'; + final emailHTML = web.document.createElement('div') as web.HTMLDivElement + ..id = viewTypeId + ..innerHTML = currentContent[0].toJS; // temporarily index because it has to do all of them + emailHTML.style + ..width = '100%' + ..height = '100%' + ..overflow = 'auto' + ..scrollBehavior = 'smooth'; + ui.platformViewRegistry.registerViewFactory( - viewTypeId, - (int viewId) => web.HTMLDivElement() - ..id = 'new-web' - ..innerHTML = currentContent as js.JSAny); - - // DivElement div = HTMLDivElement() - // ..id = - - // ui.platformViewRegistry.registerViewFactory( - // viewTypeId, - // (int viewId) => html.IFrameElement() - // ..width = '100%' - // ..height = '100%' - // ..srcdoc = currentContent - // ..style.border = 'none'); + viewTypeId, + (int viewId) => emailHTML, + ); }); } @@ -565,13 +578,18 @@ class _EmailViewState extends State { ) ], ), - Expanded( - child: HtmlElementView( - key: UniqueKey(), - viewType: viewTypeId, + child: CollapsableEmails( + thread: widget.messages, + threadHTML: widget.emailContent, ), ), + // Expanded( + // child: HtmlElementView( + // key: UniqueKey(), + // viewType: viewTypeId, + // ), + // ), ], ), From ceadc0b73d700e62f73eee977340e998874f4009 Mon Sep 17 00:00:00 2001 From: juan Date: Sun, 18 May 2025 20:51:54 -0400 Subject: [PATCH 14/19] Collapsable Emails create a ListTile and upon clicking one it expans and show the html --- lib/collapsableEmails.dart | 130 +++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 lib/collapsableEmails.dart diff --git a/lib/collapsableEmails.dart b/lib/collapsableEmails.dart new file mode 100644 index 0000000..224f097 --- /dev/null +++ b/lib/collapsableEmails.dart @@ -0,0 +1,130 @@ +import 'dart:js_interop'; +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 thread; // email id's in the form xyz@gmail.com + final List threadHTML; + + CollapsableEmails({required this.thread, required this.threadHTML}); + + @override + State createState() => _CollapsableEmailsState(); +} + +class _CollapsableEmailsState extends State { + List emailsHTML = []; //html of the emails in the thread + // build attachments with the forldar name and id + Set _expandedEmails = {}; //open emails + List viewtypeIDs = []; //IDs of the viewtypes, order matters + List heightOfViewTypes = []; //the height of each viewtype + + @override + void initState() { + // TODO: implement initState + super.initState(); + _registerViewFactory(widget.threadHTML); + } + + void _registerViewFactory(List 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); + } + + // viewTypeId = 'iframe-${DateTime.now().millisecondsSinceEpoch}'; + // final emailHTML = web.document.createElement('div') as web.HTMLDivElement + // ..id = viewTypeId + // ..innerHTML = currentContent[0].toJS; // temporarily index because it has to do all of them + // emailHTML.style + // ..width = '100%' + // ..height = '100%' + // ..overflow = 'auto' + // ..scrollBehavior = 'smooth'; + + // ui.platformViewRegistry.registerViewFactory( + // viewTypeId, + // (int viewId) => emailHTML, + // ); + // }); + } + + @override + Widget build(BuildContext context) { + return 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("email $index"), + onTap: () { + setState(() { + if (isExpanded) { + _expandedEmails.remove(index); + } else { + _expandedEmails.add(index); + } + }); + }, + ), + if (isExpanded) + // if(viewtypeIDs[index] == null || heightOfViewTypes[index] == null) + // const SizedBox(height: 100, child: Center(child: CircularProgressIndicator())), + SizedBox( + height:heightOfViewTypes[index].toDouble(), + child: HtmlElementView( + key: UniqueKey(), viewType: viewtypeIDs[index]), + ), + Divider(), + ], + ); + }, + ), + ) + ]); + } +} From 6feb357a39c41d9a32e6ca3e5cbd7f17a066fd24 Mon Sep 17 00:00:00 2001 From: juan Date: Sun, 18 May 2025 20:52:40 -0400 Subject: [PATCH 15/19] refactored the emailView --- lib/email.dart | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/email.dart b/lib/email.dart index 12b9b83..1914c78 100644 --- a/lib/email.dart +++ b/lib/email.dart @@ -5,7 +5,7 @@ import 'structs.dart'; class EmailListScreen extends StatelessWidget { final List emails; - final Future Function(List, String) getEmailContent; + final Future> Function(List, String) getEmailContent; final String folder; EmailListScreen( @@ -29,11 +29,14 @@ class EmailListScreen extends StatelessWidget { ), trailing: Text(email.date.toString()), onTap: () async { - String emailContent = + List emailContent = // list of the html await getEmailContent(email.messages, folder); + List emailIds = email.messages; + + print(email.messages); //email ids of the thread Navigator.push( context, - MaterialPageRoute( + MaterialPageRoute( // could call collapsable and inside collable each calls email view? builder: (context) => EmailView( emailContent: emailContent, from: email.from_address, @@ -42,6 +45,7 @@ class EmailListScreen extends StatelessWidget { subject: email.subject, date: email.date.toString(), id: email.id.toString(), //i think this is thread id? + messages: email.messages, ), ), ); @@ -91,8 +95,6 @@ class EmailPageState extends State { _fetchEmails(); } - // String getPage() => widget.page.toString(); - void updatePagenation(String option) { if (option == "next") { setState(() { From 95697efdab0b74fc113ddd789e47022adef51efc Mon Sep 17 00:00:00 2001 From: juan Date: Sun, 18 May 2025 20:53:05 -0400 Subject: [PATCH 16/19] fixed drawer closing --- lib/folder_drawer.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/folder_drawer.dart b/lib/folder_drawer.dart index edc7eca..2743fe3 100644 --- a/lib/folder_drawer.dart +++ b/lib/folder_drawer.dart @@ -77,7 +77,9 @@ class _FolderDrawerState extends State { title: Text('Refresh Folders'), onTap: () { _fetchFolders(); // Refresh folders when this tile is tapped - Navigator.pop(context); // Close the drawer after refresh + // rebuild + + // Navigator.pop(context); // Close the drawer after refresh }, ), ], From 7ec032c0f29ae1ebd8851eb089a978157dda1d90 Mon Sep 17 00:00:00 2001 From: juan Date: Mon, 19 May 2025 19:01:48 -0400 Subject: [PATCH 17/19] added sender and time to the email tile inside of the thread --- lib/collapsableEmails.dart | 104 +++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/lib/collapsableEmails.dart b/lib/collapsableEmails.dart index 224f097..ceed92a 100644 --- a/lib/collapsableEmails.dart +++ b/lib/collapsableEmails.dart @@ -8,8 +8,12 @@ import 'structs.dart'; class CollapsableEmails extends StatefulWidget { final List thread; // email id's in the form xyz@gmail.com final List threadHTML; + final String threadIDs; - CollapsableEmails({required this.thread, required this.threadHTML}); + CollapsableEmails( + {required this.thread, + required this.threadHTML, + required this.threadIDs}); @override State createState() => _CollapsableEmailsState(); @@ -21,12 +25,15 @@ class _CollapsableEmailsState extends State { Set _expandedEmails = {}; //open emails List viewtypeIDs = []; //IDs of the viewtypes, order matters List heightOfViewTypes = []; //the height of each viewtype + List emailsInThread = []; + bool _isLoaded = false; @override void initState() { // TODO: implement initState super.initState(); _registerViewFactory(widget.threadHTML); + _serializableData(widget.threadIDs); } void _registerViewFactory(List currentContent) async { @@ -70,61 +77,56 @@ class _CollapsableEmailsState extends State { viewtypeIDs.add(viewTypeId); heightOfViewTypes.add(heightOfEmail); } + } - // viewTypeId = 'iframe-${DateTime.now().millisecondsSinceEpoch}'; - // final emailHTML = web.document.createElement('div') as web.HTMLDivElement - // ..id = viewTypeId - // ..innerHTML = currentContent[0].toJS; // temporarily index because it has to do all of them - // emailHTML.style - // ..width = '100%' - // ..height = '100%' - // ..overflow = 'auto' - // ..scrollBehavior = 'smooth'; - - // ui.platformViewRegistry.registerViewFactory( - // viewTypeId, - // (int viewId) => emailHTML, - // ); - // }); + void _serializableData(String threadID) async { + emailsInThread = await ApiService().threadsInSerializable(threadID); + print("done thread serializable"); + if (!mounted) return; + setState(() { + _isLoaded = true; + }); } @override Widget build(BuildContext context) { - return 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("email $index"), - onTap: () { - setState(() { - if (isExpanded) { - _expandedEmails.remove(index); - } else { - _expandedEmails.add(index); - } - }); - }, - ), - if (isExpanded) - // if(viewtypeIDs[index] == null || heightOfViewTypes[index] == null) - // const SizedBox(height: 100, child: Center(child: CircularProgressIndicator())), - SizedBox( - height:heightOfViewTypes[index].toDouble(), - child: HtmlElementView( - key: UniqueKey(), viewType: viewtypeIDs[index]), + 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); + } + }); + }, ), - Divider(), - ], - ); - }, - ), - ) - ]); + if (isExpanded) + // if(viewtypeIDs[index] == null || heightOfViewTypes[index] == null) + // const SizedBox(height: 100, child: Center(child: CircularProgressIndicator())), + SizedBox( + height: heightOfViewTypes[index].toDouble(), + child: HtmlElementView( + key: UniqueKey(), viewType: viewtypeIDs[index]), + ), + Divider(), + ], + ); + }, + ), + ) + ]): const Center(child:CircularProgressIndicator()); } } From 29f18b6876c5f84c65288d0993d27a870cbfa711 Mon Sep 17 00:00:00 2001 From: juan Date: Mon, 19 May 2025 19:02:51 -0400 Subject: [PATCH 18/19] cleaned and commented out useless viewtype registry siunce using collapsable --- lib/api_service.dart | 54 +++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/lib/api_service.dart b/lib/api_service.dart index a9b6b20..aa05b99 100644 --- a/lib/api_service.dart +++ b/lib/api_service.dart @@ -7,7 +7,6 @@ import 'dart:typed_data'; import 'package:pointer_interceptor/pointer_interceptor.dart'; import 'collapsableEmails.dart'; - import 'structs.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; @@ -156,6 +155,7 @@ class ApiService { Future> threadsInSerializable( String thread_id) async { + //actually a number // grab all of the emails in thread anyways, for the future it'll come in handy var url = Uri.http('$ip:$port', 'get_thread_messages', {'id': thread_id}); try { @@ -462,44 +462,40 @@ class _EmailViewState extends State { {'id': 'marker2', 'x': 150, 'y': 200}, {'id': 'marker3', 'x': 250, 'y': 300}, ]; - ApiService _apiService = ApiService(); @override void initState() { super.initState(); + print("thread id? ${widget.id}"); List 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}"; - _registerViewFactory(currentContent); - // _markerPositionsFuture = ApiService().getMarkerPosition(); + // _registerViewFactory(currentContent); } - void _registerViewFactory(List currentContent) { - setState(() { //update to do item per item - // each item to have itsviewtype ID - // is this necessarey here?? + // void _registerViewFactory(List currentContent) { // i think this doesnt work anymore + // setState(() { //update to do item per item + // // each item to have itsviewtype ID + // // is this necessarey here?? - //could just move to collapsable + // //could just move to collapsable + // viewTypeId = 'iframe-${DateTime.now().millisecondsSinceEpoch}'; + // final emailHTML = web.document.createElement('div') as web.HTMLDivElement + // ..id = viewTypeId + // ..innerHTML = currentContent[0].toJS; // temporarily index because it has to do all of them + // emailHTML.style + // ..width = '100%' + // ..height = '100%' + // ..overflow = 'auto' + // ..scrollBehavior = 'smooth'; - - viewTypeId = 'iframe-${DateTime.now().millisecondsSinceEpoch}'; - final emailHTML = web.document.createElement('div') as web.HTMLDivElement - ..id = viewTypeId - ..innerHTML = currentContent[0].toJS; // temporarily index because it has to do all of them - emailHTML.style - ..width = '100%' - ..height = '100%' - ..overflow = 'auto' - ..scrollBehavior = 'smooth'; - - ui.platformViewRegistry.registerViewFactory( - viewTypeId, - (int viewId) => emailHTML, - ); - }); - } + // ui.platformViewRegistry.registerViewFactory( + // viewTypeId, + // (int viewId) => emailHTML, + // ); + // }); + // } void _scrollToNumber(String spanId) { AugmentClasses.handleJump(spanId); @@ -508,7 +504,7 @@ class _EmailViewState extends State { // TODO: void _invisibility(String ) //to make purple numbers not visible @override - Widget build(BuildContext context) { + Widget build(BuildContext context) { // print("thread id ${widget.id}"); ApiService.currThreadID = widget.id; return Scaffold( @@ -580,8 +576,10 @@ class _EmailViewState extends State { ), Expanded( child: CollapsableEmails( + //change here thread: widget.messages, threadHTML: widget.emailContent, + threadIDs: widget.id, ), ), // Expanded( From 80afd26c67d4c4bab1d8148aa6167361030c1e96 Mon Sep 17 00:00:00 2001 From: juan Date: Tue, 20 May 2025 17:04:50 -0400 Subject: [PATCH 19/19] created an email view for the result of a Sonic query, since the results is in individual Serializable emails, instead of the whole thread --- lib/api_service.dart | 9 ++- lib/email.dart | 10 +-- lib/home_page.dart | 37 ++++++---- lib/sonicEmailView.dart | 145 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 22 deletions(-) create mode 100644 lib/sonicEmailView.dart diff --git a/lib/api_service.dart b/lib/api_service.dart index aa05b99..b0b92ea 100644 --- a/lib/api_service.dart +++ b/lib/api_service.dart @@ -101,7 +101,6 @@ class ApiService { List messagesJson = json.decode(response.body); List messages = messagesJson.map((mj) => SerializableMessage.fromJson(mj)).toList(); - return messages; } print(response.statusCode); @@ -155,8 +154,8 @@ class ApiService { Future> threadsInSerializable( String thread_id) async { - //actually a number - // grab all of the emails in thread anyways, for the future it'll come in handy + //actually a xyzwtv@gmail.com + // grab all of the emails in thread anyways, for the future it'll come in handy // maybe not var url = Uri.http('$ip:$port', 'get_thread_messages', {'id': thread_id}); try { var response = await http.get(url); @@ -504,7 +503,7 @@ class _EmailViewState extends State { // TODO: void _invisibility(String ) //to make purple numbers not visible @override - Widget build(BuildContext context) { + Widget build(BuildContext context) { // print("thread id ${widget.id}"); ApiService.currThreadID = widget.id; return Scaffold( @@ -577,7 +576,7 @@ class _EmailViewState extends State { Expanded( child: CollapsableEmails( //change here - thread: widget.messages, + thread: widget.messages, //this wont work in serializable threadHTML: widget.emailContent, threadIDs: widget.id, ), diff --git a/lib/email.dart b/lib/email.dart index 1914c78..5dbf1a6 100644 --- a/lib/email.dart +++ b/lib/email.dart @@ -31,12 +31,14 @@ class EmailListScreen extends StatelessWidget { onTap: () async { List emailContent = // list of the html await getEmailContent(email.messages, folder); - List emailIds = email.messages; - - print(email.messages); //email ids of the thread + // print("this is what email.messages look like in email.dart ${email.messages}"); + // List emailIds = email.messages; + + print(email.messages); //email ids of the thread Navigator.push( context, - MaterialPageRoute( // could call collapsable and inside collable each calls email view? + MaterialPageRoute( + // could call collapsable and inside collable each calls email view? builder: (context) => EmailView( emailContent: emailContent, from: email.from_address, diff --git a/lib/home_page.dart b/lib/home_page.dart index 03ae481..b4878b0 100644 --- a/lib/home_page.dart +++ b/lib/home_page.dart @@ -1,3 +1,5 @@ +import 'package:crab_ui/sonicEmailView.dart'; + import 'folder_drawer.dart'; import 'structs.dart'; import 'package:flutter/widgets.dart'; @@ -131,22 +133,31 @@ class _HomeScreenState extends State with TickerProviderStateMixin { trailing: Text(email.date.toString()), onTap: () async { // print('tapped'); - String emailContent = - await apiService.fetchEmailContent([email.id], email.list); - // print('content below'); - // print(emailContent); + // List emailContent = + // await apiService.fetchEmailContent([email.id], email.list); + //call the foldable + + List emailContent = // list of the html + await apiService.fetchEmailContent([email.id], email.list); + // List emailIds = email.messages; + + Navigator.push( context, MaterialPageRoute( - builder: (context) => EmailView( - emailContent: emailContent, - from: email.from, - name: email.name, - to: email.to.toString(), - subject: email.subject, - date: email.date.toString(), - id: email.id.toString(), - ), + builder: (context) =>SonicEmailView( + email: email, + emailHTML: emailContent[0]) + // builder: (context) => EmailView( + // emailContent: emailContent, + // from: email.from, + // name: email.name, + // to: email.to.toString(), + // subject: email.subject, + // date: email.date.toString(), + // id: email.id.toString(), + // messages: [email.id], + // ), ), ); }, diff --git a/lib/sonicEmailView.dart b/lib/sonicEmailView.dart new file mode 100644 index 0000000..bfe0bbe --- /dev/null +++ b/lib/sonicEmailView.dart @@ -0,0 +1,145 @@ +import 'package:crab_ui/augment.dart'; +import 'package:web/web.dart' as web; +import 'dart:ui_web' as ui; +import 'dart:js_interop'; +import 'structs.dart'; +import 'package:flutter/material.dart'; + +class SonicEmailView extends StatefulWidget { + SerializableMessage email; + String emailHTML; + + SonicEmailView({required this.email, required this.emailHTML}); + + @override + _SonicEmailViewState createState() => _SonicEmailViewState(); +} + +class _SonicEmailViewState extends State { + String viewTypeIDs = ""; + int heightOFViewtype = 0; + bool _isLoaded = false; + + void _scrollToNumber(String spanId) { + AugmentClasses.handleJump(spanId); + } + + @override + void initState() { + super.initState(); + _init(); + } + + Future _init() async { + await _registerViewFactory(widget.emailHTML); + if (!mounted) return; + setState(() { + _isLoaded = true; + }); + } + + Future _registerViewFactory(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 = currentContent.toJS; + 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 = widget + .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, + ); + this.viewTypeIDs = viewTypeId; + this.heightOFViewtype = heightOfEmail; + print(viewTypeIDs); + } + + @override + Widget build(BuildContext context) { + return _isLoaded + ? Scaffold( + appBar: AppBar(title: Text(widget.email.subject)), + body: Stack( + children: [ + Column( + children: [ + EmailToolbar( + onButtonPressed: () => {}, + onJumpToSpan: _scrollToNumber), + Row( + // title of email + children: [ + Text( + widget.email.subject, + style: TextStyle(fontSize: 30), + ), + ], + ), + Row( + children: [ + Text( + 'from ${widget.email.name}', + style: TextStyle(fontSize: 18), + ), + Text( + '<${widget.email.from}>', + style: TextStyle(fontSize: 18), + ), + Spacer(), + Text( + '${widget.email.date}', + textAlign: TextAlign.right, + ) + ], + ), + // TODO: make a case where if one of these is the user's email it just says me :))))) + Row( + children: [ + Text( + 'to ${widget.email.to.toString()}', + style: TextStyle(fontSize: 15), + ) + ], + ), + Expanded( + // child: SizedBox( + // height: heightOFViewtype.toDouble(), + child: HtmlElementView( + key: UniqueKey(), viewType: this.viewTypeIDs, + // ), + )) + ], + ), + ], + ), + ) + : const Center( + child: CircularProgressIndicator(), + ); + } +}