flip_library_callback.c 31 KB

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