flip_store_callback.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. #include <callback/flip_store_callback.h>
  2. bool flip_store_app_does_exist = false;
  3. uint32_t selected_firmware_index = 0;
  4. // Callback for drawing the main screen
  5. void flip_store_view_draw_callback_main(Canvas* canvas, void* model) {
  6. UNUSED(model);
  7. canvas_set_font(canvas, FontSecondary);
  8. if(fhttp.state == INACTIVE) {
  9. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  10. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  11. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  12. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  13. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  14. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  15. return;
  16. }
  17. if(!flip_store_sent_request) {
  18. flip_store_sent_request = true;
  19. if(!flip_store_install_app(canvas, categories[flip_store_category_index])) {
  20. canvas_clear(canvas);
  21. canvas_draw_str(canvas, 0, 10, "Failed to install app.");
  22. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  23. }
  24. } else {
  25. if(flip_store_success) {
  26. if(fhttp.state == RECEIVING) {
  27. canvas_clear(canvas);
  28. canvas_draw_str(canvas, 0, 10, "Downloading app...");
  29. canvas_draw_str(canvas, 0, 60, "Please wait...");
  30. return;
  31. } else if(fhttp.state == IDLE) {
  32. canvas_clear(canvas);
  33. canvas_draw_str(canvas, 0, 10, "App installed successfully.");
  34. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  35. }
  36. } else {
  37. canvas_clear(canvas);
  38. canvas_draw_str(canvas, 0, 10, "Failed to install app.");
  39. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  40. }
  41. }
  42. }
  43. // Function to draw the firmware download screen
  44. void flip_store_view_draw_callback_firmware(Canvas* canvas, void* model) {
  45. UNUSED(model);
  46. // Check if the HTTP state is inactive
  47. if(fhttp.state == INACTIVE) {
  48. canvas_set_font(canvas, FontSecondary);
  49. canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
  50. canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
  51. canvas_draw_str(canvas, 0, 32, "If your board is connected,");
  52. canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
  53. canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
  54. canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
  55. return;
  56. }
  57. // Set font and clear the canvas for the loading state
  58. canvas_set_font(canvas, FontSecondary);
  59. canvas_clear(canvas);
  60. canvas_draw_str(canvas, 0, 10, "Loading...");
  61. // Handle first firmware file
  62. if(!sent_firmware_request) {
  63. sent_firmware_request = true;
  64. firmware_request_success = flip_store_get_firmware_file(
  65. firmwares[selected_firmware_index].links[0],
  66. firmwares[selected_firmware_index].name,
  67. strrchr(firmwares[selected_firmware_index].links[0], '/') + 1);
  68. if(!firmware_request_success) {
  69. canvas_set_font(canvas, FontSecondary);
  70. canvas_clear(canvas);
  71. flip_store_request_error(canvas);
  72. }
  73. return;
  74. } else if(sent_firmware_request && !firmware_download_success) {
  75. if(!firmware_request_success || fhttp.state == ISSUE) {
  76. canvas_set_font(canvas, FontSecondary);
  77. canvas_clear(canvas);
  78. flip_store_request_error(canvas);
  79. } else if(fhttp.state == RECEIVING) {
  80. canvas_set_font(canvas, FontSecondary);
  81. canvas_clear(canvas);
  82. canvas_draw_str(canvas, 0, 10, "Downloading file 1...");
  83. canvas_draw_str(canvas, 0, 60, "Please wait...");
  84. } else if(fhttp.state == IDLE) {
  85. canvas_set_font(canvas, FontSecondary);
  86. canvas_clear(canvas);
  87. canvas_draw_str(canvas, 0, 10, "Success");
  88. canvas_draw_str(canvas, 0, 60, "Downloading the next file now.");
  89. firmware_download_success = true;
  90. }
  91. return;
  92. }
  93. // Handle second firmware file
  94. if(firmware_download_success && !sent_firmware_request_2) {
  95. sent_firmware_request_2 = true;
  96. firmware_request_success_2 = flip_store_get_firmware_file(
  97. firmwares[selected_firmware_index].links[1],
  98. firmwares[selected_firmware_index].name,
  99. strrchr(firmwares[selected_firmware_index].links[1], '/') + 1);
  100. if(!firmware_request_success_2) {
  101. canvas_set_font(canvas, FontSecondary);
  102. canvas_clear(canvas);
  103. flip_store_request_error(canvas);
  104. }
  105. return;
  106. } else if(sent_firmware_request_2 && !firmware_download_success_2) {
  107. if(!firmware_request_success_2 || fhttp.state == ISSUE) {
  108. canvas_set_font(canvas, FontSecondary);
  109. canvas_clear(canvas);
  110. flip_store_request_error(canvas);
  111. } else if(fhttp.state == RECEIVING) {
  112. canvas_set_font(canvas, FontSecondary);
  113. canvas_clear(canvas);
  114. canvas_draw_str(canvas, 0, 10, "Downloading file 2...");
  115. canvas_draw_str(canvas, 0, 60, "Please wait...");
  116. } else if(fhttp.state == IDLE) {
  117. canvas_set_font(canvas, FontSecondary);
  118. canvas_clear(canvas);
  119. canvas_draw_str(canvas, 0, 10, "Success");
  120. canvas_draw_str(canvas, 0, 60, "Downloading the next file now.");
  121. firmware_download_success_2 = true;
  122. }
  123. return;
  124. }
  125. // Handle third firmware file
  126. if(firmware_download_success && firmware_download_success_2 && !sent_firmware_request_3) {
  127. sent_firmware_request_3 = true;
  128. firmware_request_success_3 = flip_store_get_firmware_file(
  129. firmwares[selected_firmware_index].links[2],
  130. firmwares[selected_firmware_index].name,
  131. strrchr(firmwares[selected_firmware_index].links[2], '/') + 1);
  132. if(!firmware_request_success_3) {
  133. canvas_set_font(canvas, FontSecondary);
  134. canvas_clear(canvas);
  135. flip_store_request_error(canvas);
  136. }
  137. return;
  138. } else if(sent_firmware_request_3 && !firmware_download_success_3) {
  139. if(!firmware_request_success_3 || fhttp.state == ISSUE) {
  140. canvas_set_font(canvas, FontSecondary);
  141. canvas_clear(canvas);
  142. flip_store_request_error(canvas);
  143. } else if(fhttp.state == RECEIVING) {
  144. canvas_set_font(canvas, FontSecondary);
  145. canvas_clear(canvas);
  146. canvas_draw_str(canvas, 0, 10, "Downloading file 3...");
  147. canvas_draw_str(canvas, 0, 60, "Please wait...");
  148. } else if(fhttp.state == IDLE) {
  149. canvas_set_font(canvas, FontSecondary);
  150. canvas_clear(canvas);
  151. canvas_draw_str(canvas, 0, 10, "Success");
  152. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  153. firmware_download_success_3 = true;
  154. }
  155. return;
  156. }
  157. // All files downloaded successfully
  158. if(firmware_download_success && firmware_download_success_2 && firmware_download_success_3) {
  159. canvas_set_font(canvas, FontSecondary);
  160. canvas_clear(canvas);
  161. canvas_draw_str(canvas, 0, 10, "Files downloaded successfully.");
  162. canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
  163. }
  164. }
  165. // Function to draw the message on the canvas with word wrapping
  166. void draw_description(Canvas* canvas, const char* description, int x, int y) {
  167. if(description == NULL || strlen(description) == 0) {
  168. FURI_LOG_E(TAG, "User message is NULL.");
  169. return;
  170. }
  171. if(!canvas) {
  172. FURI_LOG_E(TAG, "Canvas is NULL.");
  173. return;
  174. }
  175. size_t msg_length = strlen(description);
  176. size_t start = 0;
  177. int line_num = 0;
  178. char line[MAX_LINE_LENGTH + 1]; // Buffer for the current line (+1 for null terminator)
  179. while(start < msg_length && line_num < 4) {
  180. size_t remaining = msg_length - start;
  181. size_t len = (remaining > MAX_LINE_LENGTH) ? MAX_LINE_LENGTH : remaining;
  182. if(remaining > MAX_LINE_LENGTH) {
  183. // Find the last space within the first 'len' characters
  184. size_t last_space = len;
  185. while(last_space > 0 && description[start + last_space - 1] != ' ') {
  186. last_space--;
  187. }
  188. if(last_space > 0) {
  189. len = last_space; // Adjust len to the position of the last space
  190. }
  191. }
  192. // Copy the substring to 'line' and null-terminate it
  193. memcpy(line, description + start, len);
  194. line[len] = '\0'; // Ensure the string is null-terminated
  195. // Draw the string on the canvas
  196. // Adjust the y-coordinate based on the line number
  197. canvas_draw_str_aligned(canvas, x, y + line_num * 10, AlignLeft, AlignTop, line);
  198. // Update the start position for the next line
  199. start += len;
  200. // Skip any spaces to avoid leading spaces on the next line
  201. while(start < msg_length && description[start] == ' ') {
  202. start++;
  203. }
  204. // Increment the line number
  205. line_num++;
  206. }
  207. }
  208. void flip_store_view_draw_callback_app_list(Canvas* canvas, void* model) {
  209. UNUSED(model);
  210. canvas_clear(canvas);
  211. canvas_set_font(canvas, FontPrimary);
  212. char title[30];
  213. snprintf(
  214. title,
  215. 30,
  216. "%s (v.%s)",
  217. flip_catalog[app_selected_index].app_name,
  218. flip_catalog[app_selected_index].app_version);
  219. canvas_draw_str(canvas, 0, 10, title);
  220. canvas_set_font(canvas, FontSecondary);
  221. draw_description(canvas, flip_catalog[app_selected_index].app_description, 0, 13);
  222. if(flip_store_app_does_exist) {
  223. canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7);
  224. canvas_draw_str_aligned(canvas, 7, 54, AlignLeft, AlignTop, "Delete");
  225. canvas_draw_icon(canvas, 45, 53, &I_ButtonBACK_10x8);
  226. canvas_draw_str_aligned(canvas, 57, 54, AlignLeft, AlignTop, "Back");
  227. } else {
  228. canvas_draw_icon(canvas, 0, 53, &I_ButtonBACK_10x8);
  229. canvas_draw_str_aligned(canvas, 12, 54, AlignLeft, AlignTop, "Back");
  230. }
  231. canvas_draw_icon(canvas, 90, 53, &I_ButtonRight_4x7);
  232. canvas_draw_str_aligned(canvas, 97, 54, AlignLeft, AlignTop, "Install");
  233. }
  234. bool flip_store_input_callback(InputEvent* event, void* context) {
  235. FlipStoreApp* app = (FlipStoreApp*)context;
  236. if(!app) {
  237. FURI_LOG_E(TAG, "FlipStoreApp is NULL");
  238. return false;
  239. }
  240. if(event->type == InputTypeShort) {
  241. if(event->key == InputKeyLeft && flip_store_app_does_exist) {
  242. // Left button clicked, delete the app
  243. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppDelete);
  244. return true;
  245. }
  246. if(event->key == InputKeyRight) {
  247. // Right button clicked, download the app
  248. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewMain);
  249. return true;
  250. }
  251. } else if(event->type == InputTypePress) {
  252. if(event->key == InputKeyBack) {
  253. // Back button clicked, switch to the previous view.
  254. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
  255. return true;
  256. }
  257. }
  258. return false;
  259. }
  260. void flip_store_text_updated_ssid(void* context) {
  261. FlipStoreApp* app = (FlipStoreApp*)context;
  262. if(!app) {
  263. FURI_LOG_E(TAG, "FlipStoreApp is NULL");
  264. return;
  265. }
  266. // store the entered text
  267. strncpy(
  268. app->uart_text_input_buffer_ssid,
  269. app->uart_text_input_temp_buffer_ssid,
  270. app->uart_text_input_buffer_size_ssid);
  271. // Ensure null-termination
  272. app->uart_text_input_buffer_ssid[app->uart_text_input_buffer_size_ssid - 1] = '\0';
  273. // update the variable item text
  274. if(app->variable_item_ssid) {
  275. variable_item_set_current_value_text(
  276. app->variable_item_ssid, app->uart_text_input_buffer_ssid);
  277. }
  278. // save the settings
  279. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_pass);
  280. // if SSID and PASS are not empty, connect to the WiFi
  281. if(strlen(app->uart_text_input_buffer_ssid) > 0 &&
  282. strlen(app->uart_text_input_buffer_pass) > 0) {
  283. // save wifi settings
  284. if(!flipper_http_save_wifi(
  285. app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_pass)) {
  286. FURI_LOG_E(TAG, "Failed to save WiFi settings");
  287. }
  288. }
  289. // switch to the settings view
  290. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSettings);
  291. }
  292. void flip_store_text_updated_pass(void* context) {
  293. FlipStoreApp* app = (FlipStoreApp*)context;
  294. if(!app) {
  295. FURI_LOG_E(TAG, "FlipStoreApp is NULL");
  296. return;
  297. }
  298. // store the entered text
  299. strncpy(
  300. app->uart_text_input_buffer_pass,
  301. app->uart_text_input_temp_buffer_pass,
  302. app->uart_text_input_buffer_size_pass);
  303. // Ensure null-termination
  304. app->uart_text_input_buffer_pass[app->uart_text_input_buffer_size_pass - 1] = '\0';
  305. // update the variable item text
  306. if(app->variable_item_pass) {
  307. variable_item_set_current_value_text(
  308. app->variable_item_pass, app->uart_text_input_buffer_pass);
  309. }
  310. // save the settings
  311. save_settings(app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_pass);
  312. // if SSID and PASS are not empty, connect to the WiFi
  313. if(strlen(app->uart_text_input_buffer_ssid) > 0 &&
  314. strlen(app->uart_text_input_buffer_pass) > 0) {
  315. // save wifi settings
  316. if(!flipper_http_save_wifi(
  317. app->uart_text_input_buffer_ssid, app->uart_text_input_buffer_pass)) {
  318. FURI_LOG_E(TAG, "Failed to save WiFi settings");
  319. }
  320. }
  321. // switch to the settings view
  322. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSettings);
  323. }
  324. uint32_t callback_to_submenu(void* context) {
  325. if(!context) {
  326. FURI_LOG_E(TAG, "Context is NULL");
  327. return VIEW_NONE;
  328. }
  329. UNUSED(context);
  330. firmware_free();
  331. return FlipStoreViewSubmenu;
  332. }
  333. uint32_t callback_to_submenu_options(void* context) {
  334. if(!context) {
  335. FURI_LOG_E(TAG, "Context is NULL");
  336. return VIEW_NONE;
  337. }
  338. UNUSED(context);
  339. firmware_free();
  340. return FlipStoreViewSubmenuOptions;
  341. }
  342. uint32_t callback_to_firmware_list(void* context) {
  343. if(!context) {
  344. FURI_LOG_E(TAG, "Context is NULL");
  345. return VIEW_NONE;
  346. }
  347. UNUSED(context);
  348. sent_firmware_request = false;
  349. sent_firmware_request_2 = false;
  350. sent_firmware_request_3 = false;
  351. //
  352. firmware_request_success = false;
  353. firmware_request_success_2 = false;
  354. firmware_request_success_3 = false;
  355. //
  356. firmware_download_success = false;
  357. firmware_download_success_2 = false;
  358. firmware_download_success_3 = false;
  359. return FlipStoreViewFirmwares;
  360. }
  361. uint32_t callback_to_app_list(void* context) {
  362. if(!context) {
  363. FURI_LOG_E(TAG, "Context is NULL");
  364. return VIEW_NONE;
  365. }
  366. UNUSED(context);
  367. flip_store_sent_request = false;
  368. flip_store_success = false;
  369. flip_store_saved_data = false;
  370. flip_store_saved_success = false;
  371. flip_store_app_does_exist = false;
  372. sent_firmware_request = false;
  373. return FlipStoreViewAppList;
  374. }
  375. void settings_item_selected(void* context, uint32_t index) {
  376. FlipStoreApp* app = (FlipStoreApp*)context;
  377. if(!app) {
  378. FURI_LOG_E(TAG, "FlipStoreApp is NULL");
  379. return;
  380. }
  381. switch(index) {
  382. case 0: // Input SSID
  383. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewTextInputSSID);
  384. break;
  385. case 1: // Input Password
  386. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewTextInputPass);
  387. break;
  388. default:
  389. FURI_LOG_E(TAG, "Unknown configuration item index");
  390. break;
  391. }
  392. }
  393. void dialog_delete_callback(DialogExResult result, void* context) {
  394. furi_assert(context);
  395. FlipStoreApp* app = (FlipStoreApp*)context;
  396. if(result == DialogExResultLeft) // No
  397. {
  398. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
  399. } else if(result == DialogExResultRight) {
  400. // delete the app then return to the app list
  401. if(!delete_app(
  402. flip_catalog[app_selected_index].app_id, categories[flip_store_category_index])) {
  403. // pop up a message
  404. popup_set_header(app->popup, "[ERROR]", 0, 0, AlignLeft, AlignTop);
  405. popup_set_text(app->popup, "Issue deleting app.", 0, 50, AlignLeft, AlignTop);
  406. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewPopup);
  407. furi_delay_ms(2000); // delay for 2 seconds
  408. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
  409. } else {
  410. // pop up a message
  411. popup_set_header(app->popup, "[SUCCESS]", 0, 0, AlignLeft, AlignTop);
  412. popup_set_text(app->popup, "App deleted successfully.", 0, 50, AlignLeft, AlignTop);
  413. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewPopup);
  414. furi_delay_ms(2000); // delay for 2 seconds
  415. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
  416. }
  417. }
  418. }
  419. void dialog_firmware_callback(DialogExResult result, void* context) {
  420. furi_assert(context);
  421. FlipStoreApp* app = (FlipStoreApp*)context;
  422. if(result == DialogExResultLeft) // No
  423. {
  424. // switch to the firmware list
  425. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewFirmwares);
  426. } else if(result == DialogExResultRight) {
  427. // download the firmware then return to the firmware list
  428. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewFirmwareDownload);
  429. }
  430. }
  431. void popup_callback(void* context) {
  432. FlipStoreApp* app = (FlipStoreApp*)context;
  433. if(!app) {
  434. FURI_LOG_E(TAG, "FlipStoreApp is NULL");
  435. return;
  436. }
  437. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSubmenu);
  438. }
  439. uint32_t callback_exit_app(void* context) {
  440. // Exit the application
  441. if(!context) {
  442. FURI_LOG_E(TAG, "Context is NULL");
  443. return VIEW_NONE;
  444. }
  445. UNUSED(context);
  446. return VIEW_NONE; // Return VIEW_NONE to exit the app
  447. }
  448. void callback_submenu_choices(void* context, uint32_t index) {
  449. FlipStoreApp* app = (FlipStoreApp*)context;
  450. if(!app) {
  451. FURI_LOG_E(TAG, "FlipStoreApp is NULL");
  452. return;
  453. }
  454. switch(index) {
  455. case FlipStoreSubmenuIndexMain:
  456. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewMain);
  457. break;
  458. case FlipStoreSubmenuIndexAbout:
  459. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAbout);
  460. break;
  461. case FlipStoreSubmenuIndexSettings:
  462. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSettings);
  463. break;
  464. case FlipStoreSubmenuIndexOptions:
  465. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSubmenuOptions);
  466. break;
  467. case FlipStoreSubmenuIndexAppList:
  468. flip_store_category_index = 0;
  469. flip_store_app_does_exist = false;
  470. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
  471. break;
  472. case FlipStoreSubmenuIndexFirmwares:
  473. if(!app->submenu_firmwares) {
  474. FURI_LOG_E(TAG, "Submenu firmwares is NULL");
  475. return;
  476. }
  477. firmwares = firmware_alloc();
  478. if(firmwares == NULL) {
  479. FURI_LOG_E(TAG, "Failed to allocate memory for firmwares");
  480. return;
  481. }
  482. submenu_reset(app->submenu_firmwares);
  483. submenu_set_header(app->submenu_firmwares, "ESP32 Firmwares");
  484. for(int i = 0; i < FIRMWARE_COUNT; i++) {
  485. submenu_add_item(
  486. app->submenu_firmwares,
  487. firmwares[i].name,
  488. FlipStoreSubmenuIndexStartFirmwares + i,
  489. callback_submenu_choices,
  490. app);
  491. }
  492. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewFirmwares);
  493. break;
  494. case FlipStoreSubmenuIndexAppListBluetooth:
  495. flip_store_category_index = 0;
  496. flip_store_app_does_exist = false;
  497. view_dispatcher_switch_to_view(
  498. app->view_dispatcher,
  499. flip_store_handle_app_list(
  500. app, FlipStoreViewAppListBluetooth, "Bluetooth", &app->submenu_app_list_bluetooth));
  501. break;
  502. case FlipStoreSubmenuIndexAppListGames:
  503. flip_store_category_index = 1;
  504. flip_store_app_does_exist = false;
  505. view_dispatcher_switch_to_view(
  506. app->view_dispatcher,
  507. flip_store_handle_app_list(
  508. app, FlipStoreViewAppListGames, "Games", &app->submenu_app_list_games));
  509. break;
  510. case FlipStoreSubmenuIndexAppListGPIO:
  511. flip_store_category_index = 2;
  512. flip_store_app_does_exist = false;
  513. view_dispatcher_switch_to_view(
  514. app->view_dispatcher,
  515. flip_store_handle_app_list(
  516. app, FlipStoreViewAppListGPIO, "GPIO", &app->submenu_app_list_gpio));
  517. break;
  518. case FlipStoreSubmenuIndexAppListInfrared:
  519. flip_store_category_index = 3;
  520. flip_store_app_does_exist = false;
  521. view_dispatcher_switch_to_view(
  522. app->view_dispatcher,
  523. flip_store_handle_app_list(
  524. app, FlipStoreViewAppListInfrared, "Infrared", &app->submenu_app_list_infrared));
  525. break;
  526. case FlipStoreSubmenuIndexAppListiButton:
  527. flip_store_category_index = 4;
  528. flip_store_app_does_exist = false;
  529. view_dispatcher_switch_to_view(
  530. app->view_dispatcher,
  531. flip_store_handle_app_list(
  532. app, FlipStoreViewAppListiButton, "iButton", &app->submenu_app_list_ibutton));
  533. break;
  534. case FlipStoreSubmenuIndexAppListMedia:
  535. flip_store_category_index = 5;
  536. flip_store_app_does_exist = false;
  537. view_dispatcher_switch_to_view(
  538. app->view_dispatcher,
  539. flip_store_handle_app_list(
  540. app, FlipStoreViewAppListMedia, "Media", &app->submenu_app_list_media));
  541. break;
  542. case FlipStoreSubmenuIndexAppListNFC:
  543. flip_store_category_index = 6;
  544. flip_store_app_does_exist = false;
  545. view_dispatcher_switch_to_view(
  546. app->view_dispatcher,
  547. flip_store_handle_app_list(
  548. app, FlipStoreViewAppListNFC, "NFC", &app->submenu_app_list_nfc));
  549. break;
  550. case FlipStoreSubmenuIndexAppListRFID:
  551. flip_store_category_index = 7;
  552. flip_store_app_does_exist = false;
  553. view_dispatcher_switch_to_view(
  554. app->view_dispatcher,
  555. flip_store_handle_app_list(
  556. app, FlipStoreViewAppListRFID, "RFID", &app->submenu_app_list_rfid));
  557. break;
  558. case FlipStoreSubmenuIndexAppListSubGHz:
  559. flip_store_category_index = 8;
  560. flip_store_app_does_exist = false;
  561. view_dispatcher_switch_to_view(
  562. app->view_dispatcher,
  563. flip_store_handle_app_list(
  564. app, FlipStoreViewAppListSubGHz, "Sub-GHz", &app->submenu_app_list_subghz));
  565. break;
  566. case FlipStoreSubmenuIndexAppListTools:
  567. flip_store_category_index = 9;
  568. flip_store_app_does_exist = false;
  569. view_dispatcher_switch_to_view(
  570. app->view_dispatcher,
  571. flip_store_handle_app_list(
  572. app, FlipStoreViewAppListTools, "Tools", &app->submenu_app_list_tools));
  573. break;
  574. case FlipStoreSubmenuIndexAppListUSB:
  575. flip_store_category_index = 10;
  576. flip_store_app_does_exist = false;
  577. view_dispatcher_switch_to_view(
  578. app->view_dispatcher,
  579. flip_store_handle_app_list(
  580. app, FlipStoreViewAppListUSB, "USB", &app->submenu_app_list_usb));
  581. break;
  582. default:
  583. // Check if the index is within the firmwares list range
  584. if(index >= FlipStoreSubmenuIndexStartFirmwares &&
  585. index < FlipStoreSubmenuIndexStartFirmwares + 3) {
  586. // Get the firmware index
  587. uint32_t firmware_index = index - FlipStoreSubmenuIndexStartFirmwares;
  588. // Check if the firmware index is valid
  589. if((int)firmware_index >= 0 && firmware_index < FIRMWARE_COUNT) {
  590. // Get the firmware name
  591. selected_firmware_index = firmware_index;
  592. // Switch to the firmware download view
  593. dialog_ex_set_header(
  594. app->dialog_firmware,
  595. firmwares[firmware_index].name,
  596. 0,
  597. 0,
  598. AlignLeft,
  599. AlignTop);
  600. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewFirmwareDialog);
  601. } else {
  602. FURI_LOG_E(TAG, "Invalid firmware index");
  603. popup_set_header(app->popup, "[ERROR]", 0, 0, AlignLeft, AlignTop);
  604. popup_set_text(app->popup, "Issue parsing firmwarex", 0, 50, AlignLeft, AlignTop);
  605. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewPopup);
  606. }
  607. }
  608. // Check if the index is within the app list range
  609. else if(
  610. index >= FlipStoreSubmenuIndexStartAppList &&
  611. index < FlipStoreSubmenuIndexStartAppList + MAX_APP_COUNT) {
  612. // Get the app index
  613. uint32_t app_index = index - FlipStoreSubmenuIndexStartAppList;
  614. // Check if the app index is valid
  615. if((int)app_index >= 0 && app_index < MAX_APP_COUNT) {
  616. // Get the app name
  617. char* app_name = flip_catalog[app_index].app_name;
  618. // Check if the app name is valid
  619. if(app_name != NULL && strlen(app_name) > 0) {
  620. app_selected_index = app_index;
  621. flip_store_app_does_exist = app_exists(
  622. flip_catalog[app_selected_index].app_id,
  623. categories[flip_store_category_index]);
  624. view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppInfo);
  625. } else {
  626. FURI_LOG_E(TAG, "Invalid app name");
  627. }
  628. } else {
  629. FURI_LOG_E(TAG, "Invalid app index");
  630. }
  631. } else {
  632. FURI_LOG_E(TAG, "Unknown submenu index");
  633. }
  634. break;
  635. }
  636. }