flip_library_callback.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. #ifndef FLIP_LIBRARY_CALLBACK_H
  2. #define FLIP_LIBRARY_CALLBACK_H
  3. static uint32_t random_facts_index = 0;
  4. static bool sent_random_fact_request = false;
  5. static bool random_fact_request_success = false;
  6. static bool random_fact_request_success_all = false;
  7. char *random_fact = NULL;
  8. static FlipLibraryApp *app_instance = NULL;
  9. #define MAX_TOKENS 512 // Adjust based on expected JSON size
  10. // Parse JSON to find the "text" key
  11. char *flip_library_parse_random_fact()
  12. {
  13. return get_json_value("text", fhttp.last_response, 128);
  14. }
  15. char *flip_library_parse_cat_fact()
  16. {
  17. return get_json_value("fact", fhttp.last_response, 128);
  18. }
  19. char *flip_library_parse_dog_fact()
  20. {
  21. return get_json_array_value("facts", 0, fhttp.last_response, 128);
  22. }
  23. char *flip_library_parse_quote()
  24. {
  25. // remove [ and ] from the start and end of the string
  26. char *response = fhttp.last_response;
  27. if (response[0] == '[')
  28. {
  29. response++;
  30. }
  31. if (response[strlen(response) - 1] == ']')
  32. {
  33. response[strlen(response) - 1] = '\0';
  34. }
  35. // remove white space from both sides
  36. while (response[0] == ' ')
  37. {
  38. response++;
  39. }
  40. while (response[strlen(response) - 1] == ' ')
  41. {
  42. response[strlen(response) - 1] = '\0';
  43. }
  44. return get_json_value("q", response, 128);
  45. }
  46. char *flip_library_parse_dictionary()
  47. {
  48. return get_json_value("definition", fhttp.last_response, 16);
  49. }
  50. static void flip_library_request_error(Canvas *canvas)
  51. {
  52. if (fhttp.last_response == NULL)
  53. {
  54. if (fhttp.last_response != NULL)
  55. {
  56. if (strstr(fhttp.last_response, "[ERROR] Not connected to Wifi. Failed to reconnect.") != NULL)
  57. {
  58. canvas_clear(canvas);
  59. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  60. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  61. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  62. }
  63. else if (strstr(fhttp.last_response, "[ERROR] Failed to connect to Wifi.") != NULL)
  64. {
  65. canvas_clear(canvas);
  66. canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
  67. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  68. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  69. }
  70. else
  71. {
  72. canvas_clear(canvas);
  73. FURI_LOG_E(TAG, "Received an error: %s", fhttp.last_response);
  74. canvas_draw_str(canvas, 0, 10, "[ERROR] Unusual error...");
  75. canvas_draw_str(canvas, 0, 60, "Press BACK and retry.");
  76. }
  77. }
  78. else
  79. {
  80. canvas_clear(canvas);
  81. canvas_draw_str(canvas, 0, 10, "[ERROR] Unknown error.");
  82. canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
  83. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  84. }
  85. }
  86. else
  87. {
  88. canvas_clear(canvas);
  89. canvas_draw_str(canvas, 0, 10, "Failed to receive data.");
  90. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  91. }
  92. }
  93. static void flip_library_draw_fact(char *message, Widget **widget)
  94. {
  95. if (app_instance == NULL)
  96. {
  97. FURI_LOG_E(TAG, "App instance is NULL");
  98. return;
  99. }
  100. widget_reset(*widget);
  101. uint32_t fact_length = strlen(message); // Length of the message
  102. uint32_t i = 0; // Index tracker
  103. uint32_t formatted_index = 0; // Tracker for where we are in the formatted message
  104. char *formatted_message; // Buffer to hold the final formatted message
  105. if (!easy_flipper_set_buffer(&formatted_message, fact_length * 2 + 1))
  106. {
  107. return;
  108. }
  109. while (i < fact_length)
  110. {
  111. uint32_t max_line_length = 29; // Maximum characters per line
  112. uint32_t remaining_length = fact_length - i; // Remaining characters
  113. uint32_t line_length = (remaining_length < max_line_length) ? remaining_length : max_line_length;
  114. // Temporary buffer to hold the current line
  115. char fact_line[30];
  116. strncpy(fact_line, message + i, line_length);
  117. fact_line[line_length] = '\0';
  118. // Check if the line ends in the middle of a word and adjust accordingly
  119. if (line_length == 29 && message[i + line_length] != '\0' && message[i + line_length] != ' ')
  120. {
  121. // Find the last space within the 30-character segment
  122. char *last_space = strrchr(fact_line, ' ');
  123. if (last_space != NULL)
  124. {
  125. // Adjust the line length to avoid cutting the word
  126. line_length = last_space - fact_line;
  127. fact_line[line_length] = '\0'; // Null-terminate at the space
  128. }
  129. }
  130. // Manually copy the fixed line into the formatted_message buffer
  131. for (uint32_t j = 0; j < line_length; j++)
  132. {
  133. formatted_message[formatted_index++] = fact_line[j];
  134. }
  135. // Add a newline character for line spacing
  136. formatted_message[formatted_index++] = '\n';
  137. // Move i forward to the start of the next word
  138. i += line_length;
  139. // Skip spaces at the beginning of the next line
  140. while (message[i] == ' ')
  141. {
  142. i++;
  143. }
  144. }
  145. // Add the formatted message to the widget
  146. widget_add_text_scroll_element(
  147. *widget,
  148. 0,
  149. 0,
  150. 128,
  151. 64,
  152. formatted_message);
  153. }
  154. // Callback for drawing the main screen
  155. static void view_draw_callback_random_facts(Canvas *canvas, void *model)
  156. {
  157. if (!canvas || !app_instance)
  158. {
  159. return;
  160. }
  161. UNUSED(model);
  162. canvas_set_font(canvas, FontSecondary);
  163. if (fhttp.state == INACTIVE)
  164. {
  165. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  166. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  167. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  168. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  169. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  170. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  171. return;
  172. }
  173. // Cats
  174. if (random_facts_index == FlipLibrarySubmenuIndexRandomFactsCats)
  175. {
  176. canvas_draw_str(canvas, 0, 7, "Random Cat Fact");
  177. canvas_draw_str(canvas, 0, 15, "Loading...");
  178. if (!sent_random_fact_request)
  179. {
  180. sent_random_fact_request = true;
  181. random_fact_request_success = flipper_http_get_request_with_headers("https://catfact.ninja/fact", "{\"Content-Type\":\"application/json\"}");
  182. if (!random_fact_request_success)
  183. {
  184. FURI_LOG_E(TAG, "Failed to send request");
  185. flip_library_request_error(canvas);
  186. return;
  187. }
  188. fhttp.state = RECEIVING;
  189. }
  190. else
  191. {
  192. if (fhttp.state == RECEIVING)
  193. {
  194. canvas_draw_str(canvas, 0, 22, "Receiving...");
  195. return;
  196. }
  197. // check status
  198. else if (fhttp.state == ISSUE || !random_fact_request_success)
  199. {
  200. flip_library_request_error(canvas);
  201. }
  202. else if (fhttp.state == IDLE && fhttp.last_response != NULL && !random_fact_request_success_all)
  203. {
  204. canvas_draw_str(canvas, 0, 22, "Processing...");
  205. // success
  206. // check status
  207. // unnecessary check
  208. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  209. {
  210. flip_library_request_error(canvas);
  211. FURI_LOG_E(TAG, "HTTP request failed or received data is NULL");
  212. return;
  213. }
  214. else if (!random_fact_request_success_all)
  215. {
  216. random_fact = flip_library_parse_cat_fact();
  217. if (random_fact == NULL)
  218. {
  219. flip_library_request_error(canvas);
  220. fhttp.state = ISSUE;
  221. return;
  222. }
  223. // Mark success
  224. random_fact_request_success_all = true;
  225. // draw random facts
  226. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  227. // go to random facts widget
  228. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  229. }
  230. }
  231. // likely redundant but just in case
  232. else if (fhttp.state == IDLE && random_fact_request_success_all && random_fact != NULL)
  233. {
  234. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  235. // go to random facts widget
  236. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  237. }
  238. else // handle weird scenarios
  239. {
  240. // if received data isnt NULL
  241. if (fhttp.last_response != NULL)
  242. {
  243. // parse json to find the text key
  244. random_fact = flip_library_parse_cat_fact();
  245. if (random_fact == NULL)
  246. {
  247. flip_library_request_error(canvas);
  248. fhttp.state = ISSUE;
  249. return;
  250. }
  251. }
  252. }
  253. }
  254. }
  255. // Dogs
  256. else if (random_facts_index == FlipLibrarySubmenuIndexRandomFactsDogs)
  257. {
  258. canvas_draw_str(canvas, 0, 7, "Random Dog Fact");
  259. canvas_draw_str(canvas, 0, 15, "Loading...");
  260. if (!sent_random_fact_request)
  261. {
  262. sent_random_fact_request = true;
  263. random_fact_request_success = flipper_http_get_request_with_headers("https://dog-api.kinduff.com/api/facts", "{\"Content-Type\":\"application/json\"}");
  264. if (!random_fact_request_success)
  265. {
  266. FURI_LOG_E(TAG, "Failed to send request");
  267. flip_library_request_error(canvas);
  268. return;
  269. }
  270. fhttp.state = RECEIVING;
  271. }
  272. else
  273. {
  274. if (fhttp.state == RECEIVING)
  275. {
  276. canvas_draw_str(canvas, 0, 22, "Receiving...");
  277. return;
  278. }
  279. // check status
  280. else if (fhttp.state == ISSUE || !random_fact_request_success)
  281. {
  282. flip_library_request_error(canvas);
  283. }
  284. else if (fhttp.state == IDLE && fhttp.last_response != NULL && !random_fact_request_success_all)
  285. {
  286. canvas_draw_str(canvas, 0, 22, "Processing...");
  287. // success
  288. // check status
  289. // unnecessary check
  290. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  291. {
  292. flip_library_request_error(canvas);
  293. FURI_LOG_E(TAG, "HTTP request failed or received data is NULL");
  294. return;
  295. }
  296. else if (!random_fact_request_success_all)
  297. {
  298. random_fact = flip_library_parse_dog_fact();
  299. if (random_fact == NULL)
  300. {
  301. flip_library_request_error(canvas);
  302. fhttp.state = ISSUE;
  303. return;
  304. }
  305. // Mark success
  306. random_fact_request_success_all = true;
  307. // draw random facts
  308. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  309. // go to random facts widget
  310. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  311. }
  312. }
  313. // likely redundant but just in case
  314. else if (fhttp.state == IDLE && random_fact_request_success_all && random_fact != NULL)
  315. {
  316. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  317. // go to random facts widget
  318. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  319. }
  320. else // handle weird scenarios
  321. {
  322. // if received data isnt NULL
  323. if (fhttp.last_response != NULL)
  324. {
  325. // parse json to find the text key
  326. random_fact = flip_library_parse_cat_fact();
  327. if (random_fact == NULL)
  328. {
  329. flip_library_request_error(canvas);
  330. fhttp.state = ISSUE;
  331. return;
  332. }
  333. }
  334. }
  335. }
  336. }
  337. // Quotes
  338. else if (random_facts_index == FlipLibrarySubmenuIndexRandomFactsQuotes)
  339. {
  340. canvas_draw_str(canvas, 0, 7, "Random Quote");
  341. canvas_draw_str(canvas, 0, 15, "Loading...");
  342. if (!sent_random_fact_request)
  343. {
  344. sent_random_fact_request = true;
  345. random_fact_request_success = flipper_http_get_request("https://zenquotes.io/api/random");
  346. if (!random_fact_request_success)
  347. {
  348. FURI_LOG_E(TAG, "Failed to send request");
  349. flip_library_request_error(canvas);
  350. return;
  351. }
  352. fhttp.state = RECEIVING;
  353. }
  354. else
  355. {
  356. if (fhttp.state == RECEIVING)
  357. {
  358. canvas_draw_str(canvas, 0, 22, "Receiving...");
  359. return;
  360. }
  361. // check status
  362. else if (fhttp.state == ISSUE || !random_fact_request_success)
  363. {
  364. flip_library_request_error(canvas);
  365. }
  366. else if (fhttp.state == IDLE && fhttp.last_response != NULL && !random_fact_request_success_all)
  367. {
  368. canvas_draw_str(canvas, 0, 22, "Processing...");
  369. // success
  370. // check status
  371. // unnecessary check
  372. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  373. {
  374. flip_library_request_error(canvas);
  375. FURI_LOG_E(TAG, "HTTP request failed or received data is NULL");
  376. return;
  377. }
  378. else if (!random_fact_request_success_all)
  379. {
  380. random_fact = flip_library_parse_quote();
  381. if (random_fact == NULL)
  382. {
  383. flip_library_request_error(canvas);
  384. fhttp.state = ISSUE;
  385. return;
  386. }
  387. // Mark success
  388. random_fact_request_success_all = true;
  389. // draw random facts
  390. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  391. // go to random facts widget
  392. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  393. }
  394. }
  395. // likely redundant but just in case
  396. else if (fhttp.state == IDLE && random_fact_request_success_all && random_fact != NULL)
  397. {
  398. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  399. // go to random facts widget
  400. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  401. }
  402. else // handle weird scenarios
  403. {
  404. // if received data isnt NULL
  405. if (fhttp.last_response != NULL)
  406. {
  407. // parse json to find the text key
  408. random_fact = flip_library_parse_quote();
  409. if (random_fact == NULL)
  410. {
  411. flip_library_request_error(canvas);
  412. fhttp.state = ISSUE;
  413. return;
  414. }
  415. }
  416. }
  417. }
  418. }
  419. // All Random Facts
  420. else if (random_facts_index == FlipLibrarySubmenuIndexRandomFactsAll)
  421. {
  422. canvas_draw_str(canvas, 0, 10, "Random Fact");
  423. canvas_set_font(canvas, FontSecondary);
  424. canvas_draw_str(canvas, 0, 20, "Loading...");
  425. if (!sent_random_fact_request)
  426. {
  427. sent_random_fact_request = true;
  428. random_fact_request_success = flipper_http_get_request("https://uselessfacts.jsph.pl/api/v2/facts/random");
  429. if (!random_fact_request_success)
  430. {
  431. FURI_LOG_E(TAG, "Failed to send request");
  432. return;
  433. }
  434. fhttp.state = RECEIVING;
  435. }
  436. else
  437. {
  438. // check status
  439. if (fhttp.state == RECEIVING)
  440. {
  441. canvas_draw_str(canvas, 0, 30, "Receiving...");
  442. return;
  443. }
  444. // check status
  445. else if (fhttp.state == ISSUE || !random_fact_request_success)
  446. {
  447. flip_library_request_error(canvas);
  448. return;
  449. }
  450. else if (fhttp.state == IDLE && fhttp.last_response != NULL && !random_fact_request_success_all)
  451. {
  452. canvas_draw_str(canvas, 0, 30, "Processing...");
  453. // success
  454. // check status
  455. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  456. {
  457. flip_library_request_error(canvas);
  458. FURI_LOG_E(TAG, "HTTP request failed or received data is NULL");
  459. return;
  460. }
  461. // parse json to find the text key
  462. random_fact = flip_library_parse_random_fact();
  463. if (random_fact == NULL)
  464. {
  465. flip_library_request_error(canvas);
  466. fhttp.state = ISSUE;
  467. return;
  468. }
  469. // Mark success
  470. random_fact_request_success_all = true;
  471. // draw random facts
  472. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  473. // go to random facts widget
  474. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  475. }
  476. // likely redundant but just in case
  477. else if (fhttp.state == IDLE && random_fact_request_success_all && random_fact != NULL)
  478. {
  479. // draw random facts
  480. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  481. // go to random facts widget
  482. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  483. }
  484. else // handle weird scenarios
  485. {
  486. // if received data isnt NULL
  487. if (fhttp.last_response != NULL)
  488. {
  489. // parse json to find the text key
  490. random_fact = flip_library_parse_random_fact();
  491. if (random_fact == NULL)
  492. {
  493. flip_library_request_error(canvas);
  494. fhttp.state = ISSUE;
  495. return;
  496. }
  497. }
  498. }
  499. }
  500. }
  501. else
  502. {
  503. canvas_draw_str(canvas, 0, 7, "Random Fact");
  504. }
  505. }
  506. static void view_draw_callback_dictionary_run(Canvas *canvas, void *model)
  507. {
  508. if (!canvas || !app_instance || app_instance->uart_text_input_buffer_dictionary == NULL)
  509. {
  510. return;
  511. }
  512. UNUSED(model);
  513. canvas_set_font(canvas, FontSecondary);
  514. if (fhttp.state == INACTIVE)
  515. {
  516. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  517. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  518. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  519. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  520. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  521. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  522. return;
  523. }
  524. canvas_draw_str(canvas, 0, 10, "Defining, please wait...");
  525. if (!sent_random_fact_request)
  526. {
  527. sent_random_fact_request = true;
  528. char payload[128];
  529. snprintf(payload, sizeof(payload), "{\"word\":\"%s\"}", app_instance->uart_text_input_buffer_dictionary);
  530. random_fact_request_success = flipper_http_post_request_with_headers("https://www.flipsocial.net/api/define/", "{\"Content-Type\":\"application/json\"}", payload);
  531. if (!random_fact_request_success)
  532. {
  533. FURI_LOG_E(TAG, "Failed to send request");
  534. return;
  535. }
  536. fhttp.state = RECEIVING;
  537. }
  538. else
  539. {
  540. // check status
  541. if (fhttp.state == RECEIVING)
  542. {
  543. canvas_draw_str(canvas, 0, 20, "Receiving...");
  544. return;
  545. }
  546. // check status
  547. else if (fhttp.state == ISSUE || !random_fact_request_success)
  548. {
  549. flip_library_request_error(canvas);
  550. return;
  551. }
  552. else if (fhttp.state == IDLE && fhttp.last_response != NULL && !random_fact_request_success_all)
  553. {
  554. canvas_draw_str(canvas, 0, 20, "Processing...");
  555. // success
  556. // check status
  557. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  558. {
  559. flip_library_request_error(canvas);
  560. FURI_LOG_E(TAG, "HTTP request failed or received data is NULL");
  561. return;
  562. }
  563. // parse json to find the text key
  564. char *definition = flip_library_parse_dictionary();
  565. if (definition == NULL)
  566. {
  567. flip_library_request_error(canvas);
  568. fhttp.state = ISSUE;
  569. return;
  570. }
  571. // Mark success
  572. random_fact_request_success_all = true;
  573. // draw random facts
  574. flip_library_draw_fact(definition, &app_instance->widget_dictionary);
  575. // go to random facts widget
  576. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewDictionaryWidget);
  577. }
  578. // likely redundant but just in case
  579. else if (fhttp.state == IDLE && random_fact_request_success_all && random_fact != NULL)
  580. {
  581. // draw random facts
  582. flip_library_draw_fact(random_fact, &app_instance->widget_dictionary);
  583. // go to random facts widget
  584. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewDictionaryWidget);
  585. }
  586. else // handle weird scenarios
  587. {
  588. // if received data isnt NULL
  589. if (fhttp.last_response != NULL)
  590. {
  591. // parse json to find the text key
  592. char *definition = flip_library_parse_dictionary();
  593. if (definition == NULL)
  594. {
  595. flip_library_request_error(canvas);
  596. fhttp.state = ISSUE;
  597. return;
  598. }
  599. // draw random facts
  600. flip_library_draw_fact(definition, &app_instance->widget_dictionary);
  601. // go to random facts widget
  602. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewDictionaryWidget);
  603. free(definition);
  604. return;
  605. }
  606. }
  607. }
  608. }
  609. // Input callback for the view (async input handling)
  610. bool view_input_callback_random_facts(InputEvent *event, void *context)
  611. {
  612. if (!event || !context)
  613. {
  614. return false;
  615. }
  616. FlipLibraryApp *app = (FlipLibraryApp *)context;
  617. if (event->type == InputTypePress && event->key == InputKeyBack)
  618. {
  619. // Exit the app when the back button is pressed
  620. view_dispatcher_stop(app->view_dispatcher);
  621. return true;
  622. }
  623. return false;
  624. }
  625. static void callback_submenu_choices(void *context, uint32_t index)
  626. {
  627. FlipLibraryApp *app = (FlipLibraryApp *)context;
  628. if (!app)
  629. {
  630. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  631. return;
  632. }
  633. switch (index)
  634. {
  635. case FlipLibrarySubmenuIndexRandomFacts:
  636. random_facts_index = 0;
  637. sent_random_fact_request = false;
  638. random_fact = NULL;
  639. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFacts);
  640. break;
  641. case FlipLibrarySubmenuIndexAbout:
  642. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewAbout);
  643. break;
  644. case FlipLibrarySubmenuIndexSettings:
  645. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewSettings);
  646. break;
  647. case FlipLibrarySubmenuIndexDictionary:
  648. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewDictionaryTextInput);
  649. break;
  650. case FlipLibrarySubmenuIndexRandomFactsCats:
  651. random_facts_index = FlipLibrarySubmenuIndexRandomFactsCats;
  652. sent_random_fact_request = false;
  653. random_fact = NULL;
  654. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFactsRun);
  655. break;
  656. case FlipLibrarySubmenuIndexRandomFactsDogs:
  657. random_facts_index = FlipLibrarySubmenuIndexRandomFactsDogs;
  658. sent_random_fact_request = false;
  659. random_fact = NULL;
  660. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFactsRun);
  661. break;
  662. case FlipLibrarySubmenuIndexRandomFactsQuotes:
  663. random_facts_index = FlipLibrarySubmenuIndexRandomFactsQuotes;
  664. sent_random_fact_request = false;
  665. random_fact = NULL;
  666. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFactsRun);
  667. break;
  668. case FlipLibrarySubmenuIndexRandomFactsAll:
  669. random_facts_index = FlipLibrarySubmenuIndexRandomFactsAll;
  670. sent_random_fact_request = false;
  671. random_fact = NULL;
  672. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFactsRun);
  673. break;
  674. default:
  675. break;
  676. }
  677. }
  678. static void text_updated_ssid(void *context)
  679. {
  680. FlipLibraryApp *app = (FlipLibraryApp *)context;
  681. if (!app)
  682. {
  683. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  684. return;
  685. }
  686. // store the entered text
  687. strncpy(app->uart_text_input_buffer_ssid, app->uart_text_input_temp_buffer_ssid, app->uart_text_input_buffer_size_ssid);
  688. // Ensure null-termination
  689. app->uart_text_input_buffer_ssid[app->uart_text_input_buffer_size_ssid - 1] = '\0';
  690. // update the variable item text
  691. if (app->variable_item_ssid)
  692. {
  693. variable_item_set_current_value_text(app->variable_item_ssid, app->uart_text_input_buffer_ssid);
  694. }
  695. // save settings
  696. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password);
  697. // save wifi settings to devboard
  698. if (strlen(app->uart_text_input_buffer_ssid) > 0 && strlen(app->uart_text_input_buffer_password) > 0)
  699. {
  700. if (!flipper_http_save_wifi(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password))
  701. {
  702. FURI_LOG_E(TAG, "Failed to save wifi settings");
  703. }
  704. }
  705. // switch to the settings view
  706. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewSettings);
  707. }
  708. static void text_updated_password(void *context)
  709. {
  710. FlipLibraryApp *app = (FlipLibraryApp *)context;
  711. if (!app)
  712. {
  713. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  714. return;
  715. }
  716. // store the entered text
  717. strncpy(app->uart_text_input_buffer_password, app->uart_text_input_temp_buffer_password, app->uart_text_input_buffer_size_password);
  718. // Ensure null-termination
  719. app->uart_text_input_buffer_password[app->uart_text_input_buffer_size_password - 1] = '\0';
  720. // update the variable item text
  721. if (app->variable_item_password)
  722. {
  723. variable_item_set_current_value_text(app->variable_item_password, app->uart_text_input_buffer_password);
  724. }
  725. // save settings
  726. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password);
  727. // save wifi settings to devboard
  728. if (strlen(app->uart_text_input_buffer_ssid) > 0 && strlen(app->uart_text_input_buffer_password) > 0)
  729. {
  730. if (!flipper_http_save_wifi(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password))
  731. {
  732. FURI_LOG_E(TAG, "Failed to save wifi settings");
  733. }
  734. }
  735. // switch to the settings view
  736. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewSettings);
  737. }
  738. static void text_updated_dictionary(void *context)
  739. {
  740. FlipLibraryApp *app = (FlipLibraryApp *)context;
  741. if (!app)
  742. {
  743. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  744. return;
  745. }
  746. // store the entered text
  747. strncpy(app->uart_text_input_buffer_dictionary, app->uart_text_input_temp_buffer_dictionary, app->uart_text_input_buffer_size_dictionary);
  748. // Ensure null-termination
  749. app->uart_text_input_buffer_dictionary[app->uart_text_input_buffer_size_dictionary - 1] = '\0';
  750. // switch to the dictionary view
  751. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewDictionaryRun);
  752. }
  753. static uint32_t callback_to_submenu(void *context)
  754. {
  755. if (!context)
  756. {
  757. FURI_LOG_E(TAG, "Context is NULL");
  758. return VIEW_NONE;
  759. }
  760. UNUSED(context);
  761. random_facts_index = 0;
  762. sent_random_fact_request = false;
  763. random_fact_request_success = false;
  764. random_fact_request_success_all = false;
  765. random_fact = NULL;
  766. return FlipLibraryViewSubmenuMain;
  767. }
  768. static uint32_t callback_to_wifi_settings(void *context)
  769. {
  770. if (!context)
  771. {
  772. FURI_LOG_E(TAG, "Context is NULL");
  773. return VIEW_NONE;
  774. }
  775. UNUSED(context);
  776. return FlipLibraryViewSettings;
  777. }
  778. static uint32_t callback_to_random_facts(void *context)
  779. {
  780. if (!context)
  781. {
  782. FURI_LOG_E(TAG, "Context is NULL");
  783. return VIEW_NONE;
  784. }
  785. UNUSED(context);
  786. return FlipLibraryViewRandomFacts;
  787. }
  788. static void settings_item_selected(void *context, uint32_t index)
  789. {
  790. FlipLibraryApp *app = (FlipLibraryApp *)context;
  791. if (!app)
  792. {
  793. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  794. return;
  795. }
  796. switch (index)
  797. {
  798. case 0: // Input SSID
  799. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewTextInputSSID);
  800. break;
  801. case 1: // Input Password
  802. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewTextInputPassword);
  803. break;
  804. default:
  805. FURI_LOG_E(TAG, "Unknown configuration item index");
  806. break;
  807. }
  808. }
  809. /**
  810. * @brief Navigation callback for exiting the application
  811. * @param context The context - unused
  812. * @return next view id (VIEW_NONE to exit the app)
  813. */
  814. static uint32_t callback_exit_app(void *context)
  815. {
  816. // Exit the application
  817. if (!context)
  818. {
  819. FURI_LOG_E(TAG, "Context is NULL");
  820. return VIEW_NONE;
  821. }
  822. UNUSED(context);
  823. return VIEW_NONE; // Return VIEW_NONE to exit the app
  824. }
  825. #endif // FLIP_LIBRARY_CALLBACK_H