flip_library_callback.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  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, 128);
  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. return;
  266. }
  267. fhttp.state = RECEIVING;
  268. }
  269. else
  270. {
  271. if (fhttp.state == RECEIVING)
  272. {
  273. canvas_draw_str(canvas, 0, 22, "Receiving...");
  274. return;
  275. }
  276. // check status
  277. else if (fhttp.state == ISSUE || !random_fact_request_success)
  278. {
  279. flip_library_request_error(canvas);
  280. }
  281. else if (fhttp.state == IDLE && fhttp.last_response != NULL && !random_fact_request_success_all)
  282. {
  283. canvas_draw_str(canvas, 0, 22, "Processing...");
  284. // success
  285. // check status
  286. // unnecessary check
  287. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  288. {
  289. flip_library_request_error(canvas);
  290. FURI_LOG_E(TAG, "HTTP request failed or received data is NULL");
  291. return;
  292. }
  293. else if (!random_fact_request_success_all)
  294. {
  295. random_fact = flip_library_parse_dog_fact();
  296. if (random_fact == NULL)
  297. {
  298. flip_library_request_error(canvas);
  299. fhttp.state = ISSUE;
  300. return;
  301. }
  302. // Mark success
  303. random_fact_request_success_all = true;
  304. // draw random facts
  305. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  306. // go to random facts widget
  307. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  308. }
  309. }
  310. // likely redundant but just in case
  311. else if (fhttp.state == IDLE && random_fact_request_success_all && random_fact != NULL)
  312. {
  313. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  314. // go to random facts widget
  315. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  316. }
  317. else // handle weird scenarios
  318. {
  319. // if received data isnt NULL
  320. if (fhttp.last_response != NULL)
  321. {
  322. // parse json to find the text key
  323. random_fact = flip_library_parse_cat_fact();
  324. if (random_fact == NULL)
  325. {
  326. flip_library_request_error(canvas);
  327. fhttp.state = ISSUE;
  328. return;
  329. }
  330. }
  331. }
  332. }
  333. }
  334. // Quotes
  335. else if (random_facts_index == FlipLibrarySubmenuIndexRandomFactsQuotes)
  336. {
  337. canvas_draw_str(canvas, 0, 7, "Random Quote");
  338. canvas_draw_str(canvas, 0, 15, "Loading...");
  339. if (!sent_random_fact_request)
  340. {
  341. sent_random_fact_request = true;
  342. random_fact_request_success = flipper_http_get_request("https://zenquotes.io/api/random");
  343. if (!random_fact_request_success)
  344. {
  345. FURI_LOG_E(TAG, "Failed to send request");
  346. flip_library_request_error(canvas);
  347. return;
  348. }
  349. fhttp.state = RECEIVING;
  350. }
  351. else
  352. {
  353. if (fhttp.state == RECEIVING)
  354. {
  355. canvas_draw_str(canvas, 0, 22, "Receiving...");
  356. return;
  357. }
  358. // check status
  359. else if (fhttp.state == ISSUE || !random_fact_request_success)
  360. {
  361. flip_library_request_error(canvas);
  362. }
  363. else if (fhttp.state == IDLE && fhttp.last_response != NULL && !random_fact_request_success_all)
  364. {
  365. canvas_draw_str(canvas, 0, 22, "Processing...");
  366. // success
  367. // check status
  368. // unnecessary check
  369. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  370. {
  371. flip_library_request_error(canvas);
  372. FURI_LOG_E(TAG, "HTTP request failed or received data is NULL");
  373. return;
  374. }
  375. else if (!random_fact_request_success_all)
  376. {
  377. random_fact = flip_library_parse_quote();
  378. if (random_fact == NULL)
  379. {
  380. flip_library_request_error(canvas);
  381. fhttp.state = ISSUE;
  382. return;
  383. }
  384. // Mark success
  385. random_fact_request_success_all = true;
  386. // draw random facts
  387. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  388. // go to random facts widget
  389. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  390. }
  391. }
  392. // likely redundant but just in case
  393. else if (fhttp.state == IDLE && random_fact_request_success_all && random_fact != NULL)
  394. {
  395. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  396. // go to random facts widget
  397. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  398. }
  399. else // handle weird scenarios
  400. {
  401. // if received data isnt NULL
  402. if (fhttp.last_response != NULL)
  403. {
  404. // parse json to find the text key
  405. random_fact = flip_library_parse_quote();
  406. if (random_fact == NULL)
  407. {
  408. flip_library_request_error(canvas);
  409. fhttp.state = ISSUE;
  410. return;
  411. }
  412. }
  413. }
  414. }
  415. }
  416. // All Random Facts
  417. else if (random_facts_index == FlipLibrarySubmenuIndexRandomFactsAll)
  418. {
  419. canvas_draw_str(canvas, 0, 10, "Random Fact");
  420. canvas_set_font(canvas, FontSecondary);
  421. canvas_draw_str(canvas, 0, 20, "Loading...");
  422. if (!sent_random_fact_request)
  423. {
  424. sent_random_fact_request = true;
  425. random_fact_request_success = flipper_http_get_request("https://uselessfacts.jsph.pl/api/v2/facts/random");
  426. if (!random_fact_request_success)
  427. {
  428. FURI_LOG_E(TAG, "Failed to send request");
  429. return;
  430. }
  431. fhttp.state = RECEIVING;
  432. }
  433. else
  434. {
  435. // check status
  436. if (fhttp.state == RECEIVING)
  437. {
  438. canvas_draw_str(canvas, 0, 30, "Receiving...");
  439. return;
  440. }
  441. // check status
  442. else if (fhttp.state == ISSUE || !random_fact_request_success)
  443. {
  444. flip_library_request_error(canvas);
  445. return;
  446. }
  447. else if (fhttp.state == IDLE && fhttp.last_response != NULL && !random_fact_request_success_all)
  448. {
  449. canvas_draw_str(canvas, 0, 30, "Processing...");
  450. // success
  451. // check status
  452. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  453. {
  454. flip_library_request_error(canvas);
  455. FURI_LOG_E(TAG, "HTTP request failed or received data is NULL");
  456. return;
  457. }
  458. // parse json to find the text key
  459. random_fact = flip_library_parse_random_fact();
  460. if (random_fact == NULL)
  461. {
  462. flip_library_request_error(canvas);
  463. fhttp.state = ISSUE;
  464. return;
  465. }
  466. // Mark success
  467. random_fact_request_success_all = true;
  468. // draw random facts
  469. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  470. // go to random facts widget
  471. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  472. }
  473. // likely redundant but just in case
  474. else if (fhttp.state == IDLE && random_fact_request_success_all && random_fact != NULL)
  475. {
  476. // draw random facts
  477. flip_library_draw_fact(random_fact, &app_instance->widget_random_fact);
  478. // go to random facts widget
  479. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewRandomFactWidget);
  480. }
  481. else // handle weird scenarios
  482. {
  483. // if received data isnt NULL
  484. if (fhttp.last_response != NULL)
  485. {
  486. // parse json to find the text key
  487. random_fact = flip_library_parse_random_fact();
  488. if (random_fact == NULL)
  489. {
  490. flip_library_request_error(canvas);
  491. fhttp.state = ISSUE;
  492. return;
  493. }
  494. }
  495. }
  496. }
  497. }
  498. else
  499. {
  500. canvas_draw_str(canvas, 0, 7, "Random Fact");
  501. }
  502. }
  503. void view_draw_callback_dictionary_run(Canvas *canvas, void *model)
  504. {
  505. if (!canvas || !app_instance || app_instance->uart_text_input_buffer_dictionary == NULL)
  506. {
  507. return;
  508. }
  509. UNUSED(model);
  510. canvas_set_font(canvas, FontSecondary);
  511. if (fhttp.state == INACTIVE)
  512. {
  513. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  514. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  515. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  516. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  517. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  518. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  519. return;
  520. }
  521. canvas_draw_str(canvas, 0, 10, "Defining, please wait...");
  522. if (!sent_random_fact_request)
  523. {
  524. sent_random_fact_request = true;
  525. char payload[128];
  526. snprintf(payload, sizeof(payload), "{\"word\":\"%s\"}", app_instance->uart_text_input_buffer_dictionary);
  527. random_fact_request_success = flipper_http_post_request_with_headers("https://www.flipsocial.net/api/define/", "{\"Content-Type\":\"application/json\"}", payload);
  528. if (!random_fact_request_success)
  529. {
  530. FURI_LOG_E(TAG, "Failed to send request");
  531. return;
  532. }
  533. fhttp.state = RECEIVING;
  534. }
  535. else
  536. {
  537. // check status
  538. if (fhttp.state == RECEIVING)
  539. {
  540. canvas_draw_str(canvas, 0, 20, "Receiving...");
  541. return;
  542. }
  543. // check status
  544. else if (fhttp.state == ISSUE || !random_fact_request_success)
  545. {
  546. flip_library_request_error(canvas);
  547. return;
  548. }
  549. else if (fhttp.state == IDLE && fhttp.last_response != NULL && !random_fact_request_success_all)
  550. {
  551. canvas_draw_str(canvas, 0, 20, "Processing...");
  552. // success
  553. // check status
  554. if (fhttp.state == ISSUE || fhttp.last_response == NULL)
  555. {
  556. flip_library_request_error(canvas);
  557. FURI_LOG_E(TAG, "HTTP request failed or received data is NULL");
  558. return;
  559. }
  560. // parse json to find the text key
  561. char *definition = flip_library_parse_dictionary();
  562. if (definition == NULL)
  563. {
  564. flip_library_request_error(canvas);
  565. fhttp.state = ISSUE;
  566. return;
  567. }
  568. // Mark success
  569. random_fact_request_success_all = true;
  570. // draw random facts
  571. flip_library_draw_fact(definition, &app_instance->widget_dictionary);
  572. // go to random facts widget
  573. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewDictionaryWidget);
  574. }
  575. // likely redundant but just in case
  576. else if (fhttp.state == IDLE && random_fact_request_success_all && random_fact != NULL)
  577. {
  578. // draw random facts
  579. flip_library_draw_fact(random_fact, &app_instance->widget_dictionary);
  580. // go to random facts widget
  581. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewDictionaryWidget);
  582. }
  583. else // handle weird scenarios
  584. {
  585. // if received data isnt NULL
  586. if (fhttp.last_response != NULL)
  587. {
  588. // parse json to find the text key
  589. char *definition = flip_library_parse_dictionary();
  590. if (definition == NULL)
  591. {
  592. flip_library_request_error(canvas);
  593. fhttp.state = ISSUE;
  594. return;
  595. }
  596. // draw random facts
  597. flip_library_draw_fact(definition, &app_instance->widget_dictionary);
  598. // go to random facts widget
  599. view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipLibraryViewDictionaryWidget);
  600. free(definition);
  601. return;
  602. }
  603. }
  604. }
  605. }
  606. // Input callback for the view (async input handling)
  607. bool view_input_callback_random_facts(InputEvent *event, void *context)
  608. {
  609. if (!event || !context)
  610. {
  611. return false;
  612. }
  613. FlipLibraryApp *app = (FlipLibraryApp *)context;
  614. if (event->type == InputTypePress && event->key == InputKeyBack)
  615. {
  616. // Exit the app when the back button is pressed
  617. view_dispatcher_stop(app->view_dispatcher);
  618. return true;
  619. }
  620. return false;
  621. }
  622. void callback_submenu_choices(void *context, uint32_t index)
  623. {
  624. FlipLibraryApp *app = (FlipLibraryApp *)context;
  625. if (!app)
  626. {
  627. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  628. return;
  629. }
  630. switch (index)
  631. {
  632. case FlipLibrarySubmenuIndexRandomFacts:
  633. random_facts_index = 0;
  634. sent_random_fact_request = false;
  635. random_fact = NULL;
  636. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFacts);
  637. break;
  638. case FlipLibrarySubmenuIndexAbout:
  639. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewAbout);
  640. break;
  641. case FlipLibrarySubmenuIndexSettings:
  642. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewSettings);
  643. break;
  644. case FlipLibrarySubmenuIndexDictionary:
  645. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewDictionaryTextInput);
  646. break;
  647. case FlipLibrarySubmenuIndexRandomFactsCats:
  648. random_facts_index = FlipLibrarySubmenuIndexRandomFactsCats;
  649. sent_random_fact_request = false;
  650. random_fact = NULL;
  651. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFactsRun);
  652. break;
  653. case FlipLibrarySubmenuIndexRandomFactsDogs:
  654. random_facts_index = FlipLibrarySubmenuIndexRandomFactsDogs;
  655. sent_random_fact_request = false;
  656. random_fact = NULL;
  657. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFactsRun);
  658. break;
  659. case FlipLibrarySubmenuIndexRandomFactsQuotes:
  660. random_facts_index = FlipLibrarySubmenuIndexRandomFactsQuotes;
  661. sent_random_fact_request = false;
  662. random_fact = NULL;
  663. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFactsRun);
  664. break;
  665. case FlipLibrarySubmenuIndexRandomFactsAll:
  666. random_facts_index = FlipLibrarySubmenuIndexRandomFactsAll;
  667. sent_random_fact_request = false;
  668. random_fact = NULL;
  669. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewRandomFactsRun);
  670. break;
  671. default:
  672. break;
  673. }
  674. }
  675. void text_updated_ssid(void *context)
  676. {
  677. FlipLibraryApp *app = (FlipLibraryApp *)context;
  678. if (!app)
  679. {
  680. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  681. return;
  682. }
  683. // store the entered text
  684. strncpy(app->uart_text_input_buffer_ssid, app->uart_text_input_temp_buffer_ssid, app->uart_text_input_buffer_size_ssid);
  685. // Ensure null-termination
  686. app->uart_text_input_buffer_ssid[app->uart_text_input_buffer_size_ssid - 1] = '\0';
  687. // update the variable item text
  688. if (app->variable_item_ssid)
  689. {
  690. variable_item_set_current_value_text(app->variable_item_ssid, app->uart_text_input_buffer_ssid);
  691. }
  692. // save settings
  693. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password);
  694. // save wifi settings to devboard
  695. if (strlen(app->uart_text_input_buffer_ssid) > 0 && strlen(app->uart_text_input_buffer_password) > 0)
  696. {
  697. if (!flipper_http_save_wifi(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password))
  698. {
  699. FURI_LOG_E(TAG, "Failed to save wifi settings");
  700. }
  701. }
  702. // switch to the settings view
  703. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewSettings);
  704. }
  705. void text_updated_password(void *context)
  706. {
  707. FlipLibraryApp *app = (FlipLibraryApp *)context;
  708. if (!app)
  709. {
  710. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  711. return;
  712. }
  713. // store the entered text
  714. strncpy(app->uart_text_input_buffer_password, app->uart_text_input_temp_buffer_password, app->uart_text_input_buffer_size_password);
  715. // Ensure null-termination
  716. app->uart_text_input_buffer_password[app->uart_text_input_buffer_size_password - 1] = '\0';
  717. // update the variable item text
  718. if (app->variable_item_password)
  719. {
  720. variable_item_set_current_value_text(app->variable_item_password, app->uart_text_input_buffer_password);
  721. }
  722. // save settings
  723. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password);
  724. // save wifi settings to devboard
  725. if (strlen(app->uart_text_input_buffer_ssid) > 0 && strlen(app->uart_text_input_buffer_password) > 0)
  726. {
  727. if (!flipper_http_save_wifi(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_password))
  728. {
  729. FURI_LOG_E(TAG, "Failed to save wifi settings");
  730. }
  731. }
  732. // switch to the settings view
  733. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewSettings);
  734. }
  735. void text_updated_dictionary(void *context)
  736. {
  737. FlipLibraryApp *app = (FlipLibraryApp *)context;
  738. if (!app)
  739. {
  740. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  741. return;
  742. }
  743. // store the entered text
  744. strncpy(app->uart_text_input_buffer_dictionary, app->uart_text_input_temp_buffer_dictionary, app->uart_text_input_buffer_size_dictionary);
  745. // Ensure null-termination
  746. app->uart_text_input_buffer_dictionary[app->uart_text_input_buffer_size_dictionary - 1] = '\0';
  747. // switch to the dictionary view
  748. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewDictionaryRun);
  749. }
  750. uint32_t callback_to_submenu(void *context)
  751. {
  752. if (!context)
  753. {
  754. FURI_LOG_E(TAG, "Context is NULL");
  755. return VIEW_NONE;
  756. }
  757. UNUSED(context);
  758. random_facts_index = 0;
  759. sent_random_fact_request = false;
  760. random_fact_request_success = false;
  761. random_fact_request_success_all = false;
  762. random_fact = NULL;
  763. return FlipLibraryViewSubmenuMain;
  764. }
  765. uint32_t callback_to_wifi_settings(void *context)
  766. {
  767. if (!context)
  768. {
  769. FURI_LOG_E(TAG, "Context is NULL");
  770. return VIEW_NONE;
  771. }
  772. UNUSED(context);
  773. return FlipLibraryViewSettings;
  774. }
  775. uint32_t callback_to_random_facts(void *context)
  776. {
  777. if (!context)
  778. {
  779. FURI_LOG_E(TAG, "Context is NULL");
  780. return VIEW_NONE;
  781. }
  782. UNUSED(context);
  783. return FlipLibraryViewRandomFacts;
  784. }
  785. void settings_item_selected(void *context, uint32_t index)
  786. {
  787. FlipLibraryApp *app = (FlipLibraryApp *)context;
  788. if (!app)
  789. {
  790. FURI_LOG_E(TAG, "FlipLibraryApp is NULL");
  791. return;
  792. }
  793. switch (index)
  794. {
  795. case 0: // Input SSID
  796. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewTextInputSSID);
  797. break;
  798. case 1: // Input Password
  799. view_dispatcher_switch_to_view(app->view_dispatcher, FlipLibraryViewTextInputPassword);
  800. break;
  801. default:
  802. FURI_LOG_E(TAG, "Unknown configuration item index");
  803. break;
  804. }
  805. }
  806. /**
  807. * @brief Navigation callback for exiting the application
  808. * @param context The context - unused
  809. * @return next view id (VIEW_NONE to exit the app)
  810. */
  811. uint32_t callback_exit_app(void *context)
  812. {
  813. // Exit the application
  814. if (!context)
  815. {
  816. FURI_LOG_E(TAG, "Context is NULL");
  817. return VIEW_NONE;
  818. }
  819. UNUSED(context);
  820. return VIEW_NONE; // Return VIEW_NONE to exit the app
  821. }