flip_library_callback.h 30 KB

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