home_page.dart 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. import 'package:crab_ui/folder_drawer.dart';
  2. import 'package:crab_ui/structs.dart';
  3. import 'package:flutter/widgets.dart';
  4. import 'api_service.dart';
  5. import 'package:flutter/material.dart';
  6. import 'email.dart';
  7. // import 'serialize.dart';
  8. class HomeScreen extends StatefulWidget {
  9. @override
  10. _HomeScreenState createState() => _HomeScreenState();
  11. }
  12. class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
  13. final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  14. final GlobalKey<EmailPageState> _emailPageKey = GlobalKey<EmailPageState>();
  15. ApiService apiService = ApiService();
  16. bool _isSidebarOpen = true;
  17. bool querySearches = false;
  18. String? _selectedOption = "INBOX";
  19. List<String> _tabs = ['Emails'];
  20. Map<String, Widget> _tabWidgets = {};
  21. TabController? _tabController;
  22. @override
  23. void initState() {
  24. super.initState();
  25. _tabController = TabController(length: _tabs.length, vsync: this);
  26. _tabWidgets['Emails'] = EmailPage(
  27. key: _emailPageKey,
  28. );
  29. }
  30. // Add a new tab based on the search
  31. void _performSearch(String query, String? list) {
  32. setState(() {
  33. if (!_tabs.contains(query)) {
  34. _tabs.add(query);
  35. _tabWidgets[query] = _buildSearchResultsWidget(
  36. query, list); // Store a different widget for this tab
  37. _tabController = TabController(length: _tabs.length, vsync: this);
  38. }
  39. });
  40. }
  41. void _showOptionsSearchDialog () async {
  42. List<String> folders = await apiService.fetchFolders();
  43. if (mounted) {
  44. showDialog(
  45. context: context,
  46. builder: (BuildContext context) {
  47. return AlertDialog(
  48. title: Text('Choose an Option'),
  49. content: Column(
  50. mainAxisSize: MainAxisSize.min,
  51. children: folders.map((option) {
  52. return ListTile(
  53. title: Text(option),
  54. leading: Radio<String>(
  55. value: option,
  56. groupValue: _selectedOption, // Bind with _selectedOption
  57. onChanged: (String? value) {
  58. setState(() {
  59. _selectedOption = value;
  60. });
  61. Navigator.of(context).pop(); // Close the dialog on selection
  62. },
  63. ),
  64. );
  65. }).toList(),
  66. ),
  67. actions: <Widget>[
  68. ElevatedButton(
  69. child: Text('Submit'),
  70. onPressed: () {
  71. Navigator.of(context).pop(); // Close the dialog
  72. ScaffoldMessenger.of(context).showSnackBar(SnackBar(
  73. content: Text('You selected: $_selectedOption'),
  74. ));
  75. },
  76. ),
  77. ],
  78. );
  79. },
  80. );}
  81. }
  82. // Remove a tab
  83. void _removeTab(int index) {
  84. if (_tabs[index] != 'Emails') {
  85. setState(() {
  86. String tabToRemove = _tabs[index];
  87. _tabs.removeAt(index);
  88. _tabWidgets
  89. .remove(tabToRemove); // Remove widget associated with the tab
  90. _tabController = TabController(length: _tabs.length, vsync: this);
  91. });
  92. }
  93. }
  94. // Build a custom widget for each search query
  95. Widget _buildSearchResultsWidget(String query, String? list) {
  96. return FutureBuilder<List<SerializableMessage>>(
  97. future: apiService.sonicSearch(list ?? "INBOX", 50, 0, query),
  98. builder: (BuildContext context,
  99. AsyncSnapshot<List<SerializableMessage>> snapshot) {
  100. if (snapshot.connectionState == ConnectionState.waiting) {
  101. return Center(child: CircularProgressIndicator());
  102. } else if (snapshot.hasError) {
  103. return Center(child: Text('Error: ${snapshot.error}'));
  104. } else if (!snapshot.hasData || snapshot.data!.isEmpty) {
  105. return Center(child: Text('No results found for: $query'));
  106. } else {
  107. List<SerializableMessage> result = snapshot.data!;
  108. return Scaffold(
  109. body: ListView.separated(
  110. itemCount: result.length,
  111. itemBuilder: (context, index) {
  112. final email = result[index];
  113. return ListTile(
  114. title: Text(email.from,
  115. style: TextStyle(fontWeight: FontWeight.bold)),
  116. subtitle: Column(
  117. crossAxisAlignment: CrossAxisAlignment.start,
  118. children: [Text(email.subject)],
  119. ),
  120. trailing: Text(email.date.toString()),
  121. onTap: () async {
  122. // print('tapped');
  123. String emailContent =
  124. await apiService.fetchEmailContent([email.id]);
  125. // print('content below');
  126. // print(emailContent);
  127. Navigator.push(
  128. context,
  129. MaterialPageRoute(
  130. builder: (context) => EmailView(
  131. emailContent: emailContent,
  132. from: email.from,
  133. name: email.name,
  134. to: email.to.toString(),
  135. subject: email.subject,
  136. date: email.date.toString(),
  137. id: email.id.toString(),
  138. ),
  139. ),
  140. );
  141. },
  142. );
  143. },
  144. separatorBuilder: (context, index) => Divider(),
  145. ),
  146. // child: Column(
  147. // mainAxisAlignment: MainAxisAlignment.center,
  148. // children: [
  149. // Text("Results for: $query", style: TextStyle(fontSize: 24)),
  150. // // Display the actual data
  151. // Text(result[0].name), // Accessing the first result safely
  152. // Text(result[0].from), // Displaying the 'from' field as an example
  153. // Text(result[0].hash),
  154. // Text(result[0].subject),
  155. // Text(result[0].uid.toString()),
  156. // Text(result[0].list),
  157. // Text(result[0].id),
  158. // // Add more fields or customize the display
  159. // // SerializableEmailListScreen(emails: result, getEmailContent: getEmailContent)
  160. // // Expanded(
  161. // // child:
  162. // // ),
  163. // ],
  164. );
  165. // );
  166. }
  167. },
  168. );
  169. }
  170. @override
  171. void dispose() {
  172. _tabController?.dispose();
  173. super.dispose();
  174. }
  175. @override
  176. Widget build(BuildContext context) {
  177. return Scaffold(
  178. key: _scaffoldKey,
  179. drawer: FolderDrawer(
  180. apiService: apiService,
  181. onFolderTap: (folder) {
  182. _emailPageKey.currentState?.updateSelectedFolder(folder);
  183. },
  184. ),
  185. body: Stack(
  186. children: [
  187. Row(
  188. children: [
  189. // Sidebar
  190. if (_isSidebarOpen)
  191. Container(
  192. width: 70,
  193. color: Color.fromARGB(17, 96, 122, 135),
  194. child: Column(
  195. crossAxisAlignment: CrossAxisAlignment.start,
  196. children: [
  197. ListTile(
  198. leading: Icon(Icons.home),
  199. onTap: () {
  200. // Navigate to Home
  201. },
  202. ),
  203. ListTile(
  204. leading: Icon(Icons.settings),
  205. onTap: () {
  206. // Navigate to Settings
  207. },
  208. ),
  209. ListTile(
  210. leading: Icon(Icons.email),
  211. onTap: () {
  212. _scaffoldKey.currentState?.openDrawer();
  213. },
  214. ),
  215. Spacer(),
  216. Padding(
  217. padding: const EdgeInsets.all(8.0),
  218. child: Align(
  219. alignment: Alignment.bottomLeft,
  220. child: IconButton(
  221. icon: Icon(Icons.close, color: Colors.white),
  222. onPressed: () {
  223. setState(() {
  224. _isSidebarOpen = false;
  225. });
  226. },
  227. ),
  228. ),
  229. ),
  230. ],
  231. ),
  232. ),
  233. // Main content
  234. Expanded(
  235. child: Column(
  236. children: [
  237. Container(
  238. padding: EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 4.0),
  239. color: Color.fromARGB(42, 36, 102, 132),
  240. child: Row(
  241. mainAxisAlignment: MainAxisAlignment.center,
  242. children: [
  243. Container(
  244. width: 800,
  245. height: 40,
  246. child: TextField(
  247. decoration: InputDecoration(
  248. hintText: 'Search...',
  249. border: OutlineInputBorder(),
  250. prefixIcon: Icon(Icons.search),
  251. ),
  252. onSubmitted: (value) {
  253. if (value.isNotEmpty) {
  254. _performSearch(value, _selectedOption);
  255. }
  256. //this is the input box i mentioned
  257. // if (value == '') {
  258. // setState(() {
  259. // querySearches = false;
  260. // });
  261. // }
  262. // Future<List<String>> results = apiService
  263. // .sonicSearch('INBOX', 20, 0, value);
  264. // // print(value);
  265. // print(results);
  266. // setState(() {
  267. // querySearches = true;
  268. // });
  269. },
  270. ),
  271. ),
  272. SizedBox(
  273. width: 16,
  274. ),
  275. Container(
  276. width: 80,
  277. height: 40,
  278. child: ElevatedButton(
  279. onPressed: _showOptionsSearchDialog,
  280. child: Icon(Icons.manage_search),
  281. ),
  282. )
  283. ],
  284. ),
  285. ),
  286. Container(
  287. padding: EdgeInsets.all(0.0),
  288. color: Color.fromARGB(42, 36, 102, 132),
  289. child: Row(
  290. children: [
  291. Container(
  292. height: 2,
  293. )
  294. ],
  295. ),
  296. ),
  297. Container(
  298. color: Color.fromARGB(255, 131, 110, 143),
  299. child: TabBar(
  300. controller: _tabController,
  301. isScrollable: true,
  302. tabs: _tabs
  303. .asMap()
  304. .entries
  305. .map((entry) => Tab(
  306. child: Row(
  307. children: [
  308. Text(entry.value),
  309. if (entry.value != 'Emails')
  310. GestureDetector(
  311. onTap: () => _removeTab(entry.key),
  312. child: Icon(Icons.close, size: 16),
  313. ),
  314. ],
  315. ),
  316. ))
  317. .toList(),
  318. labelColor: Colors.white,
  319. indicatorColor: Colors.white,
  320. ),
  321. ),
  322. Container(
  323. // alignment: Alignment.topLeft,
  324. padding: EdgeInsets.all(8.0),
  325. color: Colors.white,
  326. child: Row(
  327. children: [
  328. ElevatedButton(
  329. onPressed: () {
  330. _emailPageKey.currentState
  331. ?.updatePagenation('back');
  332. },
  333. child: Icon(Icons.navigate_before),
  334. ),
  335. Text(_emailPageKey.currentState?.getPage() ?? '1'),
  336. ElevatedButton(
  337. onPressed: () {
  338. _emailPageKey.currentState
  339. ?.updatePagenation('next');
  340. },
  341. child: Icon(Icons.navigate_next),
  342. ),
  343. ],
  344. ),
  345. ),
  346. Expanded(
  347. child: TabBarView(
  348. controller: _tabController,
  349. children: _tabs.map((tab) {
  350. return _tabWidgets[tab] ??
  351. Center(child: Text("No content found"));
  352. // return Center(
  353. // child: EmailPage(
  354. // key: _emailPageKey,
  355. // ));
  356. }).toList(),
  357. ),
  358. ),
  359. // if (_tabs.isEmpty)
  360. // Expanded(
  361. // child: EmailPage(key: _emailPageKey),
  362. // ),
  363. // if (_tabs.isNotEmpty)
  364. // Expanded(
  365. // // child: Text('supposed to be mails'),
  366. // child: TabBarView(
  367. // controller: _tabController,
  368. // children: _tabs
  369. // .map((tab) => Center(child: Text('Results for $tab')))
  370. // .toList(),
  371. // ),
  372. // ),
  373. ],
  374. ),
  375. ),
  376. ],
  377. ),
  378. if (!_isSidebarOpen)
  379. Positioned(
  380. bottom: 16,
  381. left: 16,
  382. child: FloatingActionButton(
  383. child: Icon(Icons.menu),
  384. onPressed: () {
  385. setState(() {
  386. _isSidebarOpen = true;
  387. });
  388. },
  389. ),
  390. ),
  391. ],
  392. ),
  393. );
  394. }
  395. }
  396. // void _showPopupMenu(BuildContext context, Offset position) async {
  397. // final RenderBox overlay =
  398. // Overlay.of(context).context.findRenderObject() as RenderBox;
  399. // await showMenu<String>(
  400. // context: context,
  401. // position: RelativeRect.fromLTRB(
  402. // position.dx,
  403. // position.dy,
  404. // overlay.size.width - position.dx,
  405. // overlay.size.height - position.dy,
  406. // ),
  407. // items: <PopupMenuEntry<String>>[
  408. // PopupMenuItem<String>(
  409. // value: 'Open',
  410. // child: Text('Open'),
  411. // ),
  412. // PopupMenuItem<String>(
  413. // value: 'Reply',
  414. // child: Text('Reply'),
  415. // ),
  416. // PopupMenuItem<String>(
  417. // value: 'Delete',
  418. // child: Text('Delete'),
  419. // ),
  420. // ],
  421. // );
  422. // }
  423. // }