|
@@ -1,5 +1,8 @@
|
|
|
#include <callback/flip_store_callback.h>
|
|
#include <callback/flip_store_callback.h>
|
|
|
|
|
|
|
|
|
|
+bool flip_store_app_does_exist = false;
|
|
|
|
|
+uint32_t selected_firmware_index = 0;
|
|
|
|
|
+
|
|
|
// Callback for drawing the main screen
|
|
// Callback for drawing the main screen
|
|
|
void flip_store_view_draw_callback_main(Canvas* canvas, void* model) {
|
|
void flip_store_view_draw_callback_main(Canvas* canvas, void* model) {
|
|
|
UNUSED(model);
|
|
UNUSED(model);
|
|
@@ -43,16 +46,214 @@ void flip_store_view_draw_callback_main(Canvas* canvas, void* model) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// Function to draw the firmware download screen
|
|
|
|
|
+void flip_store_view_draw_callback_firmware(Canvas* canvas, void* model) {
|
|
|
|
|
+ UNUSED(model);
|
|
|
|
|
+
|
|
|
|
|
+ // Check if the HTTP state is inactive
|
|
|
|
|
+ if(fhttp.state == INACTIVE) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 32, "If your board is connected,");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Set font and clear the canvas for the loading state
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 10, "Loading...");
|
|
|
|
|
+
|
|
|
|
|
+ // Handle first firmware file
|
|
|
|
|
+ if(!sent_firmware_request) {
|
|
|
|
|
+ sent_firmware_request = true;
|
|
|
|
|
+ firmware_request_success = flip_store_get_firmware_file(
|
|
|
|
|
+ firmwares[selected_firmware_index].links[0],
|
|
|
|
|
+ firmwares[selected_firmware_index].name,
|
|
|
|
|
+ strrchr(firmwares[selected_firmware_index].links[0], '/') + 1);
|
|
|
|
|
+
|
|
|
|
|
+ if(!firmware_request_success) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ flip_store_request_error(canvas);
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ } else if(sent_firmware_request && !firmware_download_success) {
|
|
|
|
|
+ if(!firmware_request_success || fhttp.state == ISSUE) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ flip_store_request_error(canvas);
|
|
|
|
|
+ } else if(fhttp.state == RECEIVING) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 10, "Downloading file 1...");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 60, "Please wait...");
|
|
|
|
|
+ } else if(fhttp.state == IDLE) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 10, "Success");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 60, "Downloading the next file now.");
|
|
|
|
|
+ firmware_download_success = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Handle second firmware file
|
|
|
|
|
+ if(firmware_download_success && !sent_firmware_request_2) {
|
|
|
|
|
+ sent_firmware_request_2 = true;
|
|
|
|
|
+ firmware_request_success_2 = flip_store_get_firmware_file(
|
|
|
|
|
+ firmwares[selected_firmware_index].links[1],
|
|
|
|
|
+ firmwares[selected_firmware_index].name,
|
|
|
|
|
+ strrchr(firmwares[selected_firmware_index].links[1], '/') + 1);
|
|
|
|
|
+
|
|
|
|
|
+ if(!firmware_request_success_2) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ flip_store_request_error(canvas);
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ } else if(sent_firmware_request_2 && !firmware_download_success_2) {
|
|
|
|
|
+ if(!firmware_request_success_2 || fhttp.state == ISSUE) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ flip_store_request_error(canvas);
|
|
|
|
|
+ } else if(fhttp.state == RECEIVING) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 10, "Downloading file 2...");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 60, "Please wait...");
|
|
|
|
|
+ } else if(fhttp.state == IDLE) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 10, "Success");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 60, "Downloading the next file now.");
|
|
|
|
|
+ firmware_download_success_2 = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Handle third firmware file
|
|
|
|
|
+ if(firmware_download_success && firmware_download_success_2 && !sent_firmware_request_3) {
|
|
|
|
|
+ sent_firmware_request_3 = true;
|
|
|
|
|
+ firmware_request_success_3 = flip_store_get_firmware_file(
|
|
|
|
|
+ firmwares[selected_firmware_index].links[2],
|
|
|
|
|
+ firmwares[selected_firmware_index].name,
|
|
|
|
|
+ strrchr(firmwares[selected_firmware_index].links[2], '/') + 1);
|
|
|
|
|
+
|
|
|
|
|
+ if(!firmware_request_success_3) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ flip_store_request_error(canvas);
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ } else if(sent_firmware_request_3 && !firmware_download_success_3) {
|
|
|
|
|
+ if(!firmware_request_success_3 || fhttp.state == ISSUE) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ flip_store_request_error(canvas);
|
|
|
|
|
+ } else if(fhttp.state == RECEIVING) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 10, "Downloading file 3...");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 60, "Please wait...");
|
|
|
|
|
+ } else if(fhttp.state == IDLE) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 10, "Success");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
|
|
|
|
|
+ firmware_download_success_3 = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // All files downloaded successfully
|
|
|
|
|
+ if(firmware_download_success && firmware_download_success_2 && firmware_download_success_3) {
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ canvas_clear(canvas);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 10, "Files downloaded successfully.");
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Function to draw the message on the canvas with word wrapping
|
|
|
|
|
+void draw_description(Canvas* canvas, const char* description, int x, int y) {
|
|
|
|
|
+ if(description == NULL || strlen(description) == 0) {
|
|
|
|
|
+ FURI_LOG_E(TAG, "User message is NULL.");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!canvas) {
|
|
|
|
|
+ FURI_LOG_E(TAG, "Canvas is NULL.");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ size_t msg_length = strlen(description);
|
|
|
|
|
+ size_t start = 0;
|
|
|
|
|
+ int line_num = 0;
|
|
|
|
|
+ char line[MAX_LINE_LENGTH + 1]; // Buffer for the current line (+1 for null terminator)
|
|
|
|
|
+
|
|
|
|
|
+ while(start < msg_length && line_num < 4) {
|
|
|
|
|
+ size_t remaining = msg_length - start;
|
|
|
|
|
+ size_t len = (remaining > MAX_LINE_LENGTH) ? MAX_LINE_LENGTH : remaining;
|
|
|
|
|
+
|
|
|
|
|
+ if(remaining > MAX_LINE_LENGTH) {
|
|
|
|
|
+ // Find the last space within the first 'len' characters
|
|
|
|
|
+ size_t last_space = len;
|
|
|
|
|
+ while(last_space > 0 && description[start + last_space - 1] != ' ') {
|
|
|
|
|
+ last_space--;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(last_space > 0) {
|
|
|
|
|
+ len = last_space; // Adjust len to the position of the last space
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Copy the substring to 'line' and null-terminate it
|
|
|
|
|
+ memcpy(line, description + start, len);
|
|
|
|
|
+ line[len] = '\0'; // Ensure the string is null-terminated
|
|
|
|
|
+
|
|
|
|
|
+ // Draw the string on the canvas
|
|
|
|
|
+ // Adjust the y-coordinate based on the line number
|
|
|
|
|
+ canvas_draw_str_aligned(canvas, x, y + line_num * 10, AlignLeft, AlignTop, line);
|
|
|
|
|
+
|
|
|
|
|
+ // Update the start position for the next line
|
|
|
|
|
+ start += len;
|
|
|
|
|
+
|
|
|
|
|
+ // Skip any spaces to avoid leading spaces on the next line
|
|
|
|
|
+ while(start < msg_length && description[start] == ' ') {
|
|
|
|
|
+ start++;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Increment the line number
|
|
|
|
|
+ line_num++;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void flip_store_view_draw_callback_app_list(Canvas* canvas, void* model) {
|
|
void flip_store_view_draw_callback_app_list(Canvas* canvas, void* model) {
|
|
|
UNUSED(model);
|
|
UNUSED(model);
|
|
|
canvas_clear(canvas);
|
|
canvas_clear(canvas);
|
|
|
canvas_set_font(canvas, FontPrimary);
|
|
canvas_set_font(canvas, FontPrimary);
|
|
|
- // Adjusted to access flip_catalog as an array of structures
|
|
|
|
|
- canvas_draw_str(canvas, 0, 10, flip_catalog[app_selected_index].app_name);
|
|
|
|
|
- // canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7); (future implementation)
|
|
|
|
|
- // canvas_draw_str_aligned(canvas, 7, 54, AlignLeft, AlignTop, "Delete"); (future implementation)
|
|
|
|
|
- canvas_draw_icon(canvas, 0, 53, &I_ButtonBACK_10x8);
|
|
|
|
|
- canvas_draw_str_aligned(canvas, 12, 54, AlignLeft, AlignTop, "Back");
|
|
|
|
|
|
|
+ char title[30];
|
|
|
|
|
+ snprintf(
|
|
|
|
|
+ title,
|
|
|
|
|
+ 30,
|
|
|
|
|
+ "%s (v.%s)",
|
|
|
|
|
+ flip_catalog[app_selected_index].app_name,
|
|
|
|
|
+ flip_catalog[app_selected_index].app_version);
|
|
|
|
|
+ canvas_draw_str(canvas, 0, 10, title);
|
|
|
|
|
+ canvas_set_font(canvas, FontSecondary);
|
|
|
|
|
+ draw_description(canvas, flip_catalog[app_selected_index].app_description, 0, 13);
|
|
|
|
|
+ if(flip_store_app_does_exist) {
|
|
|
|
|
+ canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7);
|
|
|
|
|
+ canvas_draw_str_aligned(canvas, 7, 54, AlignLeft, AlignTop, "Delete");
|
|
|
|
|
+ canvas_draw_icon(canvas, 45, 53, &I_ButtonBACK_10x8);
|
|
|
|
|
+ canvas_draw_str_aligned(canvas, 57, 54, AlignLeft, AlignTop, "Back");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ canvas_draw_icon(canvas, 0, 53, &I_ButtonBACK_10x8);
|
|
|
|
|
+ canvas_draw_str_aligned(canvas, 12, 54, AlignLeft, AlignTop, "Back");
|
|
|
|
|
+ }
|
|
|
canvas_draw_icon(canvas, 90, 53, &I_ButtonRight_4x7);
|
|
canvas_draw_icon(canvas, 90, 53, &I_ButtonRight_4x7);
|
|
|
canvas_draw_str_aligned(canvas, 97, 54, AlignLeft, AlignTop, "Install");
|
|
canvas_draw_str_aligned(canvas, 97, 54, AlignLeft, AlignTop, "Install");
|
|
|
}
|
|
}
|
|
@@ -64,13 +265,11 @@ bool flip_store_input_callback(InputEvent* event, void* context) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
if(event->type == InputTypeShort) {
|
|
if(event->type == InputTypeShort) {
|
|
|
- // Future implementation
|
|
|
|
|
- // if (event->key == InputKeyLeft)
|
|
|
|
|
- //{
|
|
|
|
|
- // Left button clicked, delete the app with DialogEx confirmation
|
|
|
|
|
- // view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppDelete);
|
|
|
|
|
- // return true;
|
|
|
|
|
- //}
|
|
|
|
|
|
|
+ if(event->key == InputKeyLeft && flip_store_app_does_exist) {
|
|
|
|
|
+ // Left button clicked, delete the app
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppDelete);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
if(event->key == InputKeyRight) {
|
|
if(event->key == InputKeyRight) {
|
|
|
// Right button clicked, download the app
|
|
// Right button clicked, download the app
|
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewMain);
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewMain);
|
|
@@ -170,9 +369,40 @@ uint32_t callback_to_submenu(void* context) {
|
|
|
return VIEW_NONE;
|
|
return VIEW_NONE;
|
|
|
}
|
|
}
|
|
|
UNUSED(context);
|
|
UNUSED(context);
|
|
|
|
|
+ firmware_free();
|
|
|
return FlipStoreViewSubmenu;
|
|
return FlipStoreViewSubmenu;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+uint32_t callback_to_submenu_options(void* context) {
|
|
|
|
|
+ if(!context) {
|
|
|
|
|
+ FURI_LOG_E(TAG, "Context is NULL");
|
|
|
|
|
+ return VIEW_NONE;
|
|
|
|
|
+ }
|
|
|
|
|
+ UNUSED(context);
|
|
|
|
|
+ firmware_free();
|
|
|
|
|
+ return FlipStoreViewSubmenuOptions;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+uint32_t callback_to_firmware_list(void* context) {
|
|
|
|
|
+ if(!context) {
|
|
|
|
|
+ FURI_LOG_E(TAG, "Context is NULL");
|
|
|
|
|
+ return VIEW_NONE;
|
|
|
|
|
+ }
|
|
|
|
|
+ UNUSED(context);
|
|
|
|
|
+ sent_firmware_request = false;
|
|
|
|
|
+ sent_firmware_request_2 = false;
|
|
|
|
|
+ sent_firmware_request_3 = false;
|
|
|
|
|
+ //
|
|
|
|
|
+ firmware_request_success = false;
|
|
|
|
|
+ firmware_request_success_2 = false;
|
|
|
|
|
+ firmware_request_success_3 = false;
|
|
|
|
|
+ //
|
|
|
|
|
+ firmware_download_success = false;
|
|
|
|
|
+ firmware_download_success_2 = false;
|
|
|
|
|
+ firmware_download_success_3 = false;
|
|
|
|
|
+ return FlipStoreViewFirmwares;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
uint32_t callback_to_app_list(void* context) {
|
|
uint32_t callback_to_app_list(void* context) {
|
|
|
if(!context) {
|
|
if(!context) {
|
|
|
FURI_LOG_E(TAG, "Context is NULL");
|
|
FURI_LOG_E(TAG, "Context is NULL");
|
|
@@ -183,6 +413,8 @@ uint32_t callback_to_app_list(void* context) {
|
|
|
flip_store_success = false;
|
|
flip_store_success = false;
|
|
|
flip_store_saved_data = false;
|
|
flip_store_saved_data = false;
|
|
|
flip_store_saved_success = false;
|
|
flip_store_saved_success = false;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
|
|
+ sent_firmware_request = false;
|
|
|
return FlipStoreViewAppList;
|
|
return FlipStoreViewAppList;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -205,7 +437,7 @@ void settings_item_selected(void* context, uint32_t index) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void dialog_callback(DialogExResult result, void* context) {
|
|
|
|
|
|
|
+void dialog_delete_callback(DialogExResult result, void* context) {
|
|
|
furi_assert(context);
|
|
furi_assert(context);
|
|
|
FlipStoreApp* app = (FlipStoreApp*)context;
|
|
FlipStoreApp* app = (FlipStoreApp*)context;
|
|
|
if(result == DialogExResultLeft) // No
|
|
if(result == DialogExResultLeft) // No
|
|
@@ -213,13 +445,35 @@ void dialog_callback(DialogExResult result, void* context) {
|
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
|
|
|
} else if(result == DialogExResultRight) {
|
|
} else if(result == DialogExResultRight) {
|
|
|
// delete the app then return to the app list
|
|
// delete the app then return to the app list
|
|
|
|
|
+ if(!delete_app(
|
|
|
|
|
+ flip_catalog[app_selected_index].app_id, categories[flip_store_category_index])) {
|
|
|
|
|
+ // pop up a message
|
|
|
|
|
+ popup_set_header(app->popup, "[ERROR]", 0, 0, AlignLeft, AlignTop);
|
|
|
|
|
+ popup_set_text(app->popup, "Issue deleting app.", 0, 50, AlignLeft, AlignTop);
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewPopup);
|
|
|
|
|
+ furi_delay_ms(2000); // delay for 2 seconds
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // pop up a message
|
|
|
|
|
+ popup_set_header(app->popup, "[SUCCESS]", 0, 0, AlignLeft, AlignTop);
|
|
|
|
|
+ popup_set_text(app->popup, "App deleted successfully.", 0, 50, AlignLeft, AlignTop);
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewPopup);
|
|
|
|
|
+ furi_delay_ms(2000); // delay for 2 seconds
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- // pop up a message
|
|
|
|
|
- popup_set_header(app->popup, "Success", 0, 0, AlignLeft, AlignTop);
|
|
|
|
|
- popup_set_text(app->popup, "App deleted successfully.", 0, 60, AlignLeft, AlignTop);
|
|
|
|
|
- view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewPopup);
|
|
|
|
|
- furi_delay_ms(2000); // delay for 2 seconds
|
|
|
|
|
- view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
|
|
|
|
|
|
|
+void dialog_firmware_callback(DialogExResult result, void* context) {
|
|
|
|
|
+ furi_assert(context);
|
|
|
|
|
+ FlipStoreApp* app = (FlipStoreApp*)context;
|
|
|
|
|
+ if(result == DialogExResultLeft) // No
|
|
|
|
|
+ {
|
|
|
|
|
+ // switch to the firmware list
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewFirmwares);
|
|
|
|
|
+ } else if(result == DialogExResultRight) {
|
|
|
|
|
+ // download the firmware then return to the firmware list
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewFirmwareDownload);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -232,11 +486,6 @@ void popup_callback(void* context) {
|
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSubmenu);
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSubmenu);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/**
|
|
|
|
|
- * @brief Navigation callback for exiting the application
|
|
|
|
|
- * @param context The context - unused
|
|
|
|
|
- * @return next view id (VIEW_NONE to exit the app)
|
|
|
|
|
- */
|
|
|
|
|
uint32_t callback_exit_app(void* context) {
|
|
uint32_t callback_exit_app(void* context) {
|
|
|
// Exit the application
|
|
// Exit the application
|
|
|
if(!context) {
|
|
if(!context) {
|
|
@@ -263,12 +512,39 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
case FlipStoreSubmenuIndexSettings:
|
|
case FlipStoreSubmenuIndexSettings:
|
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSettings);
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSettings);
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case FlipStoreSubmenuIndexOptions:
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewSubmenuOptions);
|
|
|
|
|
+ break;
|
|
|
case FlipStoreSubmenuIndexAppList:
|
|
case FlipStoreSubmenuIndexAppList:
|
|
|
flip_store_category_index = 0;
|
|
flip_store_category_index = 0;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppList);
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case FlipStoreSubmenuIndexFirmwares:
|
|
|
|
|
+ if(!app->submenu_firmwares) {
|
|
|
|
|
+ FURI_LOG_E(TAG, "Submenu firmwares is NULL");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ firmwares = firmware_alloc();
|
|
|
|
|
+ if(firmwares == NULL) {
|
|
|
|
|
+ FURI_LOG_E(TAG, "Failed to allocate memory for firmwares");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ submenu_reset(app->submenu_firmwares);
|
|
|
|
|
+ submenu_set_header(app->submenu_firmwares, "ESP32 Firmwares");
|
|
|
|
|
+ for(int i = 0; i < FIRMWARE_COUNT; i++) {
|
|
|
|
|
+ submenu_add_item(
|
|
|
|
|
+ app->submenu_firmwares,
|
|
|
|
|
+ firmwares[i].name,
|
|
|
|
|
+ FlipStoreSubmenuIndexStartFirmwares + i,
|
|
|
|
|
+ callback_submenu_choices,
|
|
|
|
|
+ app);
|
|
|
|
|
+ }
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewFirmwares);
|
|
|
|
|
+ break;
|
|
|
case FlipStoreSubmenuIndexAppListBluetooth:
|
|
case FlipStoreSubmenuIndexAppListBluetooth:
|
|
|
flip_store_category_index = 0;
|
|
flip_store_category_index = 0;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -276,6 +552,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListGames:
|
|
case FlipStoreSubmenuIndexAppListGames:
|
|
|
flip_store_category_index = 1;
|
|
flip_store_category_index = 1;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -283,6 +560,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListGPIO:
|
|
case FlipStoreSubmenuIndexAppListGPIO:
|
|
|
flip_store_category_index = 2;
|
|
flip_store_category_index = 2;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -290,6 +568,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListInfrared:
|
|
case FlipStoreSubmenuIndexAppListInfrared:
|
|
|
flip_store_category_index = 3;
|
|
flip_store_category_index = 3;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -297,6 +576,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListiButton:
|
|
case FlipStoreSubmenuIndexAppListiButton:
|
|
|
flip_store_category_index = 4;
|
|
flip_store_category_index = 4;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -304,6 +584,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListMedia:
|
|
case FlipStoreSubmenuIndexAppListMedia:
|
|
|
flip_store_category_index = 5;
|
|
flip_store_category_index = 5;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -311,6 +592,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListNFC:
|
|
case FlipStoreSubmenuIndexAppListNFC:
|
|
|
flip_store_category_index = 6;
|
|
flip_store_category_index = 6;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -318,6 +600,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListRFID:
|
|
case FlipStoreSubmenuIndexAppListRFID:
|
|
|
flip_store_category_index = 7;
|
|
flip_store_category_index = 7;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -325,6 +608,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListSubGHz:
|
|
case FlipStoreSubmenuIndexAppListSubGHz:
|
|
|
flip_store_category_index = 8;
|
|
flip_store_category_index = 8;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -332,6 +616,7 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListTools:
|
|
case FlipStoreSubmenuIndexAppListTools:
|
|
|
flip_store_category_index = 9;
|
|
flip_store_category_index = 9;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
@@ -339,15 +624,44 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
break;
|
|
break;
|
|
|
case FlipStoreSubmenuIndexAppListUSB:
|
|
case FlipStoreSubmenuIndexAppListUSB:
|
|
|
flip_store_category_index = 10;
|
|
flip_store_category_index = 10;
|
|
|
|
|
+ flip_store_app_does_exist = false;
|
|
|
view_dispatcher_switch_to_view(
|
|
view_dispatcher_switch_to_view(
|
|
|
app->view_dispatcher,
|
|
app->view_dispatcher,
|
|
|
flip_store_handle_app_list(
|
|
flip_store_handle_app_list(
|
|
|
app, FlipStoreViewAppListUSB, "USB", &app->submenu_app_list_usb));
|
|
app, FlipStoreViewAppListUSB, "USB", &app->submenu_app_list_usb));
|
|
|
break;
|
|
break;
|
|
|
default:
|
|
default:
|
|
|
|
|
+ // Check if the index is within the firmwares list range
|
|
|
|
|
+ if(index >= FlipStoreSubmenuIndexStartFirmwares &&
|
|
|
|
|
+ index < FlipStoreSubmenuIndexStartFirmwares + 3) {
|
|
|
|
|
+ // Get the firmware index
|
|
|
|
|
+ uint32_t firmware_index = index - FlipStoreSubmenuIndexStartFirmwares;
|
|
|
|
|
+
|
|
|
|
|
+ // Check if the firmware index is valid
|
|
|
|
|
+ if((int)firmware_index >= 0 && firmware_index < FIRMWARE_COUNT) {
|
|
|
|
|
+ // Get the firmware name
|
|
|
|
|
+ selected_firmware_index = firmware_index;
|
|
|
|
|
+
|
|
|
|
|
+ // Switch to the firmware download view
|
|
|
|
|
+ dialog_ex_set_header(
|
|
|
|
|
+ app->dialog_firmware,
|
|
|
|
|
+ firmwares[firmware_index].name,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ AlignLeft,
|
|
|
|
|
+ AlignTop);
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewFirmwareDialog);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ FURI_LOG_E(TAG, "Invalid firmware index");
|
|
|
|
|
+ popup_set_header(app->popup, "[ERROR]", 0, 0, AlignLeft, AlignTop);
|
|
|
|
|
+ popup_set_text(app->popup, "Issue parsing firmwarex", 0, 50, AlignLeft, AlignTop);
|
|
|
|
|
+ view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewPopup);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
// Check if the index is within the app list range
|
|
// Check if the index is within the app list range
|
|
|
- if(index >= FlipStoreSubmenuIndexStartAppList &&
|
|
|
|
|
- index < FlipStoreSubmenuIndexStartAppList + MAX_APP_COUNT) {
|
|
|
|
|
|
|
+ else if(
|
|
|
|
|
+ index >= FlipStoreSubmenuIndexStartAppList &&
|
|
|
|
|
+ index < FlipStoreSubmenuIndexStartAppList + MAX_APP_COUNT) {
|
|
|
// Get the app index
|
|
// Get the app index
|
|
|
uint32_t app_index = index - FlipStoreSubmenuIndexStartAppList;
|
|
uint32_t app_index = index - FlipStoreSubmenuIndexStartAppList;
|
|
|
|
|
|
|
@@ -359,6 +673,9 @@ void callback_submenu_choices(void* context, uint32_t index) {
|
|
|
// Check if the app name is valid
|
|
// Check if the app name is valid
|
|
|
if(app_name != NULL && strlen(app_name) > 0) {
|
|
if(app_name != NULL && strlen(app_name) > 0) {
|
|
|
app_selected_index = app_index;
|
|
app_selected_index = app_index;
|
|
|
|
|
+ flip_store_app_does_exist = app_exists(
|
|
|
|
|
+ flip_catalog[app_selected_index].app_id,
|
|
|
|
|
+ categories[flip_store_category_index]);
|
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppInfo);
|
|
view_dispatcher_switch_to_view(app->view_dispatcher, FlipStoreViewAppInfo);
|
|
|
} else {
|
|
} else {
|
|
|
FURI_LOG_E(TAG, "Invalid app name");
|
|
FURI_LOG_E(TAG, "Invalid app name");
|