jblanked 1 год назад
Родитель
Сommit
50181e9110
11 измененных файлов с 712 добавлено и 332 удалено
  1. BIN
      .DS_Store
  2. 8 2
      CHANGELOG.md
  3. 3 6
      application.fam
  4. BIN
      assets/.DS_Store
  5. BIN
      assets/FlipperHTTP/.DS_Store
  6. 0 10
      assets/FlipperHTTP/flipper_http.h
  7. 593 0
      easy_flipper.h
  8. 20 26
      flipper_http.h
  9. 1 19
      web_crawler_callback.h
  10. 1 11
      web_crawler_e.h
  11. 86 258
      web_crawler_i.h

+ 8 - 2
CHANGELOG.md

@@ -1,3 +1,9 @@
+## 0.5 (Cleanup)
+- Refactored using the easy flipper library
+- New python library for the FlipperHTTP flash
+- Removed unnecessary GPIO initialization
+- Removed unnecessary logging
+
 ## 0.4 (New Keyboard and HTTP Methods)
 - Updated the text input to match the text input from the UART Terminal app (big thanks to xMasterx)
 - Added POST, DELETE, and PUT requests (with payloads)
@@ -5,7 +11,7 @@
 - Added more error handling
 
 ## 0.3 (New Features)
-- Updated the progress messages displayed after sending a GET request.
+- Updated the progress messages displayed after sending a HTTP request.
 - Renamed the "Config" main submenu option to "Settings."
 - Added a submenu (WiFi, File, Request) that appears when users click the "Settings" option.
 
@@ -23,7 +29,7 @@ Clicking **Request** displays a variable item list with a single text input opti
 
 ## 0.2 (Stability Patch)
 - Changed serial functions from synchronous to asynchronous.
-- Added error handling for GET requests and WiFi Dev Board connections.
+- Added error handling for HTTP requests and WiFi Dev Board connections.
 - Updated the WiFi Dev Board firmware (FlipperHTTP) to blink the green LED three times when the board is first connected, remain solid green when the board receives a serial command, and stay solid green while processing.
 - Added auto-connect and auto-disconnect for WiFi when a user enters or exits the app.
 - Added an option to view saved data.

+ 3 - 6
application.fam

@@ -4,14 +4,11 @@ App(
     apptype=FlipperAppType.EXTERNAL,
     entry_point="web_crawler_app",
     stack_size=4 * 1024,
-    requires=[
-        "gui", 
-    ],
-    order=10,
-    fap_version = (0, 4),
     fap_icon="app.png",
     fap_category="GPIO",
-    fap_author="JBlanked",
     fap_icon_assets="assets",
     fap_description="Use Wi-Fi to access the internet and scrape data from the web.",
+    fap_author="JBlanked",
+    fap_weburl="https://github.com/jblanked/WebCrawler-FlipperZero",
+    fap_version = "0.5",
 )

BIN
assets/.DS_Store


BIN
assets/FlipperHTTP/.DS_Store


+ 0 - 10
assets/FlipperHTTP/flipper_http.h

@@ -42,12 +42,6 @@ bool flipper_http_delete_request_with_headers(const char *url, const char *heade
 bool flipper_http_save_received_data(size_t bytes_received, const char line_buffer[]);
 static char *trim(const char *str);
 
-// Define GPIO pins for UART
-GpioPin test_pins[2] = {
-    {.port = GPIOA, .pin = LL_GPIO_PIN_7}, // USART1_RX
-    {.port = GPIOA, .pin = LL_GPIO_PIN_6}  // USART1_TX
-};
-
 // State variable to track the UART state
 typedef enum
 {
@@ -253,10 +247,6 @@ bool flipper_http_init(FlipperHTTP_Callback callback, void *context)
     furi_thread_start(fhttp.rx_thread);
     fhttp.rx_thread_id = furi_thread_get_id(fhttp.rx_thread);
 
-    // Initialize GPIO pins for UART
-    furi_hal_gpio_init_simple(&test_pins[0], GpioModeInput);
-    furi_hal_gpio_init_simple(&test_pins[1], GpioModeOutputPushPull);
-
     // handle when the UART control is busy to avoid furi_check failed
     if (furi_hal_serial_control_is_busy(UART_CH))
     {

+ 593 - 0
easy_flipper.h

@@ -0,0 +1,593 @@
+#ifndef EASY_FLIPPER_H
+#define EASY_FLIPPER_H
+
+#include <malloc.h>
+#include <furi.h>
+#include <furi_hal.h>
+#include <gui/gui.h>
+#include <gui/view.h>
+#include <gui/modules/submenu.h>
+#include <gui/view_dispatcher.h>
+#include <gui/modules/menu.h>
+#include <gui/modules/submenu.h>
+#include <gui/modules/widget.h>
+#include <gui/modules/text_input.h>
+#include <gui/modules/text_box.h>
+#include <gui/modules/variable_item_list.h>
+#include <gui/modules/dialog_ex.h>
+#include <gui/modules/popup.h>
+#include <gui/modules/loading.h>
+#include <uart_text_input.h>
+
+#define EASY_TAG "EasyFlipper"
+
+/**
+ * @brief Navigation callback for exiting the application
+ * @param context The context - unused
+ * @return next view id (VIEW_NONE to exit the app)
+ */
+uint32_t easy_flipper_callback_exit_app(void *context)
+{
+    // Exit the application
+    if (!context)
+    {
+        FURI_LOG_E(EASY_TAG, "Context is NULL");
+        return VIEW_NONE;
+    }
+    UNUSED(context);
+    return VIEW_NONE; // Return VIEW_NONE to exit the app
+}
+
+/**
+ * @brief Initialize a buffer
+ * @param buffer The buffer to initialize
+ * @param buffer_size The size of the buffer
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_buffer(char **buffer, uint32_t buffer_size)
+{
+    if (!buffer)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_buffer");
+        return false;
+    }
+    *buffer = (char *)malloc(buffer_size);
+    if (!*buffer)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate buffer");
+        return false;
+    }
+    *buffer[0] = '\0';
+    return true;
+}
+
+/**
+ * @brief Initialize a View object
+ * @param view The View object to initialize
+ * @param view_id The ID/Index of the view
+ * @param draw_callback The draw callback function (set to NULL if not needed)
+ * @param input_callback The input callback function (set to NULL if not needed)
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_view(
+    View **view,
+    int32_t view_id,
+    void draw_callback(Canvas *, void *),
+    bool input_callback(InputEvent *, void *),
+    uint32_t (*previous_callback)(void *),
+    ViewDispatcher **view_dispatcher,
+    void *context)
+{
+    if (!view || !view_dispatcher)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_view");
+        return false;
+    }
+    *view = view_alloc();
+    if (!*view)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate View");
+        return false;
+    }
+    if (draw_callback)
+    {
+        view_set_draw_callback(*view, draw_callback);
+    }
+    if (input_callback)
+    {
+        view_set_input_callback(*view, input_callback);
+    }
+    if (context)
+    {
+        view_set_context(*view, context);
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(*view, previous_callback);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, *view);
+    return true;
+}
+
+/**
+ * @brief Initialize a ViewDispatcher object
+ * @param view_dispatcher The ViewDispatcher object to initialize
+ * @param gui The GUI object
+ * @param context The context to pass to the event callback
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_view_dispatcher(ViewDispatcher **view_dispatcher, Gui *gui, void *context)
+{
+    if (!view_dispatcher)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_view_dispatcher");
+        return false;
+    }
+    *view_dispatcher = view_dispatcher_alloc();
+    if (!*view_dispatcher)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate ViewDispatcher");
+        return false;
+    }
+    view_dispatcher_attach_to_gui(*view_dispatcher, gui, ViewDispatcherTypeFullscreen);
+    if (context)
+    {
+        view_dispatcher_set_event_callback_context(*view_dispatcher, context);
+    }
+    return true;
+}
+
+/**
+ * @brief Initialize a Submenu object
+ * @note This does not set the items in the submenu
+ * @param submenu The Submenu object to initialize
+ * @param view_id The ID/Index of the view
+ * @param title The title/header of the submenu
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_submenu(
+    Submenu **submenu,
+    int32_t view_id,
+    char *title,
+    uint32_t(previous_callback)(void *),
+    ViewDispatcher **view_dispatcher)
+{
+    if (!submenu)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_submenu");
+        return false;
+    }
+    *submenu = submenu_alloc();
+    if (!*submenu)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate Submenu");
+        return false;
+    }
+    if (title)
+    {
+        submenu_set_header(*submenu, title);
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(submenu_get_view(*submenu), previous_callback);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, submenu_get_view(*submenu));
+    return true;
+}
+/**
+ * @brief Initialize a Menu object
+ * @note This does not set the items in the menu
+ * @param menu The Menu object to initialize
+ * @param view_id The ID/Index of the view
+ * @param item_callback The item callback function
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_menu(
+    Menu **menu,
+    int32_t view_id,
+    uint32_t(previous_callback)(void *),
+    ViewDispatcher **view_dispatcher)
+{
+    if (!menu)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_menu");
+        return false;
+    }
+    *menu = menu_alloc();
+    if (!*menu)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate Menu");
+        return false;
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(menu_get_view(*menu), previous_callback);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, menu_get_view(*menu));
+    return true;
+}
+
+/**
+ * @brief Initialize a Widget object
+ * @param widget The Widget object to initialize
+ * @param view_id The ID/Index of the view
+ * @param text The text to display in the widget
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_widget(
+    Widget **widget,
+    int32_t view_id,
+    char *text,
+    uint32_t(previous_callback)(void *),
+    ViewDispatcher **view_dispatcher)
+{
+    if (!widget)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_widget");
+        return false;
+    }
+    *widget = widget_alloc();
+    if (!*widget)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate Widget");
+        return false;
+    }
+    if (text)
+    {
+        widget_add_text_scroll_element(*widget, 0, 0, 128, 64, text);
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(widget_get_view(*widget), previous_callback);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, widget_get_view(*widget));
+    return true;
+}
+
+/**
+ * @brief Initialize a VariableItemList object
+ * @note This does not set the items in the VariableItemList
+ * @param variable_item_list The VariableItemList object to initialize
+ * @param view_id The ID/Index of the view
+ * @param enter_callback The enter callback function (can be set to NULL)
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @param context The context to pass to the enter callback (usually the app)
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_variable_item_list(
+    VariableItemList **variable_item_list,
+    int32_t view_id,
+    void (*enter_callback)(void *, uint32_t),
+    uint32_t(previous_callback)(void *),
+    ViewDispatcher **view_dispatcher,
+    void *context)
+{
+    if (!variable_item_list)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_variable_item_list");
+        return false;
+    }
+    *variable_item_list = variable_item_list_alloc();
+    if (!*variable_item_list)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate VariableItemList");
+        return false;
+    }
+    if (enter_callback)
+    {
+        variable_item_list_set_enter_callback(*variable_item_list, enter_callback, context);
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(variable_item_list_get_view(*variable_item_list), previous_callback);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, variable_item_list_get_view(*variable_item_list));
+    return true;
+}
+
+/**
+ * @brief Initialize a TextInput object
+ * @param text_input The TextInput object to initialize
+ * @param view_id The ID/Index of the view
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_text_input(
+    TextInput **text_input,
+    int32_t view_id,
+    char *header_text,
+    char *text_input_temp_buffer,
+    uint32_t text_input_buffer_size,
+    void (*result_callback)(void *),
+    uint32_t(previous_callback)(void *),
+    ViewDispatcher **view_dispatcher,
+    void *context)
+{
+    if (!text_input)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_text_input");
+        return false;
+    }
+    *text_input = text_input_alloc();
+    if (!*text_input)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate TextInput");
+        return false;
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(text_input_get_view(*text_input), previous_callback);
+    }
+    if (header_text)
+    {
+        text_input_set_header_text(*text_input, header_text);
+    }
+    if (text_input_temp_buffer && text_input_buffer_size && result_callback)
+    {
+        text_input_set_result_callback(*text_input, result_callback, context, text_input_temp_buffer, text_input_buffer_size, false);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, text_input_get_view(*text_input));
+    return true;
+}
+
+/**
+ * @brief Initialize a UART_TextInput object
+ * @param uart_text_input The UART_TextInput object to initialize
+ * @param view_id The ID/Index of the view
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_uart_text_input(
+    UART_TextInput **uart_text_input,
+    int32_t view_id,
+    char *header_text,
+    char *uart_text_input_temp_buffer,
+    uint32_t uart_text_input_buffer_size,
+    void (*result_callback)(void *),
+    uint32_t(previous_callback)(void *),
+    ViewDispatcher **view_dispatcher,
+    void *context)
+{
+    if (!uart_text_input)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_uart_text_input");
+        return false;
+    }
+    *uart_text_input = uart_text_input_alloc();
+    if (!*uart_text_input)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate UART_TextInput");
+        return false;
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(uart_text_input_get_view(*uart_text_input), previous_callback);
+    }
+    if (header_text)
+    {
+        uart_text_input_set_header_text(*uart_text_input, header_text);
+    }
+    if (uart_text_input_temp_buffer && uart_text_input_buffer_size && result_callback)
+    {
+        uart_text_input_set_result_callback(*uart_text_input, result_callback, context, uart_text_input_temp_buffer, uart_text_input_buffer_size, false);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, uart_text_input_get_view(*uart_text_input));
+    return true;
+}
+
+/**
+ * @brief Initialize a DialogEx object
+ * @param dialog_ex The DialogEx object to initialize
+ * @param view_id The ID/Index of the view
+ * @param header The header of the dialog
+ * @param header_x The x coordinate of the header
+ * @param header_y The y coordinate of the header
+ * @param text The text of the dialog
+ * @param text_x The x coordinate of the dialog
+ * @param text_y The y coordinate of the dialog
+ * @param left_button_text The text of the left button
+ * @param right_button_text The text of the right button
+ * @param center_button_text The text of the center button
+ * @param result_callback The result callback function
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @param context The context to pass to the result callback
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_dialog_ex(
+    DialogEx **dialog_ex,
+    int32_t view_id,
+    char *header,
+    uint16_t header_x,
+    uint16_t header_y,
+    char *text,
+    uint16_t text_x,
+    uint16_t text_y,
+    char *left_button_text,
+    char *right_button_text,
+    char *center_button_text,
+    void (*result_callback)(DialogExResult, void *),
+    uint32_t(previous_callback)(void *),
+    ViewDispatcher **view_dispatcher,
+    void *context)
+{
+    if (!dialog_ex)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_dialog_ex");
+        return false;
+    }
+    *dialog_ex = dialog_ex_alloc();
+    if (!*dialog_ex)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate DialogEx");
+        return false;
+    }
+    if (header)
+    {
+        dialog_ex_set_header(*dialog_ex, header, header_x, header_y, AlignLeft, AlignTop);
+    }
+    if (text)
+    {
+        dialog_ex_set_text(*dialog_ex, text, text_x, text_y, AlignLeft, AlignTop);
+    }
+    if (left_button_text)
+    {
+        dialog_ex_set_left_button_text(*dialog_ex, left_button_text);
+    }
+    if (right_button_text)
+    {
+        dialog_ex_set_right_button_text(*dialog_ex, right_button_text);
+    }
+    if (center_button_text)
+    {
+        dialog_ex_set_center_button_text(*dialog_ex, center_button_text);
+    }
+    if (result_callback)
+    {
+        dialog_ex_set_result_callback(*dialog_ex, result_callback);
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(dialog_ex_get_view(*dialog_ex), previous_callback);
+    }
+    if (context)
+    {
+        dialog_ex_set_context(*dialog_ex, context);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, dialog_ex_get_view(*dialog_ex));
+    return true;
+}
+
+/**
+ * @brief Initialize a Popup object
+ * @param popup The Popup object to initialize
+ * @param view_id The ID/Index of the view
+ * @param header The header of the dialog
+ * @param header_x The x coordinate of the header
+ * @param header_y The y coordinate of the header
+ * @param text The text of the dialog
+ * @param text_x The x coordinate of the dialog
+ * @param text_y The y coordinate of the dialog
+ * @param result_callback The result callback function
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @param context The context to pass to the result callback
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_popup(
+    Popup **popup,
+    int32_t view_id,
+    char *header,
+    uint16_t header_x,
+    uint16_t header_y,
+    char *text,
+    uint16_t text_x,
+    uint16_t text_y,
+    void (*result_callback)(void *),
+    uint32_t(previous_callback)(void *),
+    ViewDispatcher **view_dispatcher,
+    void *context)
+{
+    if (!popup)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_popup");
+        return false;
+    }
+    *popup = popup_alloc();
+    if (!*popup)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate Popup");
+        return false;
+    }
+    if (header)
+    {
+        popup_set_header(*popup, header, header_x, header_y, AlignLeft, AlignTop);
+    }
+    if (text)
+    {
+        popup_set_text(*popup, text, text_x, text_y, AlignLeft, AlignTop);
+    }
+    if (result_callback)
+    {
+        popup_set_callback(*popup, result_callback);
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(popup_get_view(*popup), previous_callback);
+    }
+    if (context)
+    {
+        popup_set_context(*popup, context);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, popup_get_view(*popup));
+    return true;
+}
+
+/**
+ * @brief Initialize a Loading object
+ * @param loading The Loading object to initialize
+ * @param view_id The ID/Index of the view
+ * @param previous_callback The previous callback function (can be set to NULL)
+ * @param view_dispatcher The ViewDispatcher object
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_loading(
+    Loading **loading,
+    int32_t view_id,
+    uint32_t(previous_callback)(void *),
+    ViewDispatcher **view_dispatcher)
+{
+    if (!loading)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_loading");
+        return false;
+    }
+    *loading = loading_alloc();
+    if (!*loading)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate Loading");
+        return false;
+    }
+    if (previous_callback)
+    {
+        view_set_previous_callback(loading_get_view(*loading), previous_callback);
+    }
+    view_dispatcher_add_view(*view_dispatcher, view_id, loading_get_view(*loading));
+    return true;
+}
+
+/**
+ * @brief Set a char butter to a FuriString
+ * @param furi_string The FuriString object
+ * @param buffer The buffer to copy the string to
+ * @return true if successful, false otherwise
+ */
+bool easy_flipper_set_char_to_furi_string(FuriString **furi_string, char *buffer)
+{
+    if (!furi_string)
+    {
+        FURI_LOG_E(EASY_TAG, "Invalid arguments provided to set_buffer_to_furi_string");
+        return false;
+    }
+    *furi_string = furi_string_alloc();
+    if (!furi_string)
+    {
+        FURI_LOG_E(EASY_TAG, "Failed to allocate FuriString");
+        return false;
+    }
+    furi_string_set_str(*furi_string, buffer);
+    return true;
+}
+
+#endif // EASY_FLIPPER_H

+ 20 - 26
flipper_http.h

@@ -42,12 +42,6 @@ bool flipper_http_delete_request_with_headers(const char *url, const char *heade
 bool flipper_http_save_received_data(size_t bytes_received, const char line_buffer[]);
 static char *trim(const char *str);
 
-// Define GPIO pins for UART
-GpioPin test_pins[2] = {
-    {.port = GPIOA, .pin = LL_GPIO_PIN_7}, // USART1_RX
-    {.port = GPIOA, .pin = LL_GPIO_PIN_6}  // USART1_TX
-};
-
 // State variable to track the UART state
 typedef enum
 {
@@ -254,8 +248,8 @@ bool flipper_http_init(FlipperHTTP_Callback callback, void *context)
     fhttp.rx_thread_id = furi_thread_get_id(fhttp.rx_thread);
 
     // Initialize GPIO pins for UART
-    furi_hal_gpio_init_simple(&test_pins[0], GpioModeInput);
-    furi_hal_gpio_init_simple(&test_pins[1], GpioModeOutputPushPull);
+    // furi_hal_gpio_init_simple(&test_pins[0], GpioModeInput);
+    // furi_hal_gpio_init_simple(&test_pins[1], GpioModeOutputPushPull);
 
     // handle when the UART control is busy to avoid furi_check failed
     if (furi_hal_serial_control_is_busy(UART_CH))
@@ -311,7 +305,7 @@ bool flipper_http_init(FlipperHTTP_Callback callback, void *context)
     // Set the timer thread priority if needed
     furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
 
-    FURI_LOG_I(HTTP_TAG, "UART initialized successfully.");
+    //(HTTP_TAG, "UART initialized successfully.");
     return true;
 }
 
@@ -367,7 +361,7 @@ void flipper_http_deinit()
         fhttp.last_response = NULL;
     }
 
-    FURI_LOG_I("FlipperHTTP", "UART deinitialized successfully.");
+    // FURI_LOG_I("FlipperHTTP", "UART deinitialized successfully.");
 }
 
 // Function to send data over UART with newline termination
@@ -725,8 +719,8 @@ void flipper_http_rx_callback(const char *line, void *context)
 
         if (strstr(line, "[GET/END]") != NULL)
         {
-            FURI_LOG_I(HTTP_TAG, "GET request completed.");
-            // Stop the timer since we've completed the GET request
+            // FURI_LOG_I(HTTP_TAG, "GET request completed.");
+            //  Stop the timer since we've completed the GET request
             furi_timer_stop(fhttp.get_timeout_timer);
 
             if (fhttp.received_data)
@@ -787,8 +781,8 @@ void flipper_http_rx_callback(const char *line, void *context)
 
         if (strstr(line, "[POST/END]") != NULL)
         {
-            FURI_LOG_I(HTTP_TAG, "POST request completed.");
-            // Stop the timer since we've completed the POST request
+            // FURI_LOG_I(HTTP_TAG, "POST request completed.");
+            //  Stop the timer since we've completed the POST request
             furi_timer_stop(fhttp.get_timeout_timer);
 
             if (fhttp.received_data)
@@ -849,8 +843,8 @@ void flipper_http_rx_callback(const char *line, void *context)
 
         if (strstr(line, "[PUT/END]") != NULL)
         {
-            FURI_LOG_I(HTTP_TAG, "PUT request completed.");
-            // Stop the timer since we've completed the PUT request
+            // FURI_LOG_I(HTTP_TAG, "PUT request completed.");
+            //  Stop the timer since we've completed the PUT request
             furi_timer_stop(fhttp.get_timeout_timer);
 
             if (fhttp.received_data)
@@ -911,8 +905,8 @@ void flipper_http_rx_callback(const char *line, void *context)
 
         if (strstr(line, "[DELETE/END]") != NULL)
         {
-            FURI_LOG_I(HTTP_TAG, "DELETE request completed.");
-            // Stop the timer since we've completed the DELETE request
+            // FURI_LOG_I(HTTP_TAG, "DELETE request completed.");
+            //  Stop the timer since we've completed the DELETE request
             furi_timer_stop(fhttp.get_timeout_timer);
 
             if (fhttp.received_data)
@@ -968,11 +962,11 @@ void flipper_http_rx_callback(const char *line, void *context)
     // Handle different types of responses
     if (strstr(line, "[SUCCESS]") != NULL || strstr(line, "[CONNECTED]") != NULL)
     {
-        FURI_LOG_I(HTTP_TAG, "Operation succeeded.");
+        // FURI_LOG_I(HTTP_TAG, "Operation succeeded.");
     }
     else if (strstr(line, "[INFO]") != NULL)
     {
-        FURI_LOG_I(HTTP_TAG, "Received info: %s", line);
+        // FURI_LOG_I(HTTP_TAG, "Received info: %s", line);
 
         if (fhttp.state == INACTIVE && strstr(line, "[INFO] Already connected to Wifi.") != NULL)
         {
@@ -981,7 +975,7 @@ void flipper_http_rx_callback(const char *line, void *context)
     }
     else if (strstr(line, "[GET/SUCCESS]") != NULL)
     {
-        FURI_LOG_I(HTTP_TAG, "GET request succeeded.");
+        // FURI_LOG_I(HTTP_TAG, "GET request succeeded.");
         fhttp.started_receiving_get = true;
         furi_timer_start(fhttp.get_timeout_timer, TIMEOUT_DURATION_TICKS);
         fhttp.state = RECEIVING;
@@ -990,7 +984,7 @@ void flipper_http_rx_callback(const char *line, void *context)
     }
     else if (strstr(line, "[POST/SUCCESS]") != NULL)
     {
-        FURI_LOG_I(HTTP_TAG, "POST request succeeded.");
+        // FURI_LOG_I(HTTP_TAG, "POST request succeeded.");
         fhttp.started_receiving_post = true;
         furi_timer_start(fhttp.get_timeout_timer, TIMEOUT_DURATION_TICKS);
         fhttp.state = RECEIVING;
@@ -999,7 +993,7 @@ void flipper_http_rx_callback(const char *line, void *context)
     }
     else if (strstr(line, "[PUT/SUCCESS]") != NULL)
     {
-        FURI_LOG_I(HTTP_TAG, "PUT request succeeded.");
+        // FURI_LOG_I(HTTP_TAG, "PUT request succeeded.");
         fhttp.started_receiving_put = true;
         furi_timer_start(fhttp.get_timeout_timer, TIMEOUT_DURATION_TICKS);
         fhttp.state = RECEIVING;
@@ -1008,7 +1002,7 @@ void flipper_http_rx_callback(const char *line, void *context)
     }
     else if (strstr(line, "[DELETE/SUCCESS]") != NULL)
     {
-        FURI_LOG_I(HTTP_TAG, "DELETE request succeeded.");
+        // FURI_LOG_I(HTTP_TAG, "DELETE request succeeded.");
         fhttp.started_receiving_delete = true;
         furi_timer_start(fhttp.get_timeout_timer, TIMEOUT_DURATION_TICKS);
         fhttp.state = RECEIVING;
@@ -1017,7 +1011,7 @@ void flipper_http_rx_callback(const char *line, void *context)
     }
     else if (strstr(line, "[DISCONNECTED]") != NULL)
     {
-        FURI_LOG_I(HTTP_TAG, "WiFi disconnected successfully.");
+        // FURI_LOG_I(HTTP_TAG, "WiFi disconnected successfully.");
     }
     else if (strstr(line, "[ERROR]") != NULL)
     {
@@ -1027,7 +1021,7 @@ void flipper_http_rx_callback(const char *line, void *context)
     }
     else if (strstr(line, "[PONG]") != NULL)
     {
-        FURI_LOG_I(HTTP_TAG, "Received PONG response: Wifi Dev Board is still alive.");
+        // FURI_LOG_I(HTTP_TAG, "Received PONG response: Wifi Dev Board is still alive.");
 
         // send command to connect to WiFi
         if (fhttp.state == INACTIVE)

+ 1 - 19
web_crawler_callback.h

@@ -59,7 +59,7 @@ static void web_crawler_view_draw_callback(Canvas *canvas, void *context)
     {
         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 you board is connected,");
+        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 Dev Board with the");
         canvas_draw_str(canvas, 0, 62, "FlipperHTTP firmware.");
@@ -483,8 +483,6 @@ static void web_crawler_set_ssid_updated(void *context)
             FURI_LOG_E(TAG, "Failed to save wifi settings via UART");
             FURI_LOG_E(TAG, "Make sure the Flipper is connected to the Wifi Dev Board");
         }
-
-        FURI_LOG_D(TAG, "SSID saved: %s", app->ssid);
     }
 
     // Return to the Configure view
@@ -524,8 +522,6 @@ static void web_crawler_set_password_update(void *context)
             FURI_LOG_E(TAG, "Failed to save wifi settings via UART");
             FURI_LOG_E(TAG, "Make sure the Flipper is connected to the Wifi Dev Board");
         }
-
-        FURI_LOG_D(TAG, "Password saved: %s", app->password);
     }
 
     // Return to the Configure view
@@ -632,8 +628,6 @@ static void web_crawler_setting_item_path_clicked(void *context, uint32_t index)
     }
 
     UNUSED(index);
-    // Set up the text input
-    uart_text_input_set_header_text(app->text_input_path, "Enter URL");
 
     // Initialize temp_buffer with existing path
     if (app->path && strlen(app->path) > 0)
@@ -695,8 +689,6 @@ static void web_crawler_setting_item_headers_clicked(void *context, uint32_t ind
         FURI_LOG_E(TAG, "Temp buffer headers is NULL");
         return;
     }
-    // Set up the text input
-    uart_text_input_set_header_text(app->text_input_headers, "Enter Headers");
 
     // Initialize temp_buffer with existing headers
     if (app->headers && strlen(app->headers) > 0)
@@ -748,8 +740,6 @@ static void web_crawler_setting_item_payload_clicked(void *context, uint32_t ind
         FURI_LOG_E(TAG, "Text input is NULL");
         return;
     }
-    // Set up the text input
-    uart_text_input_set_header_text(app->text_input_payload, "Enter Payload");
 
     // Initialize temp_buffer with existing payload
     if (app->payload && strlen(app->payload) > 0)
@@ -801,8 +791,6 @@ static void web_crawler_setting_item_ssid_clicked(void *context, uint32_t index)
         FURI_LOG_E(TAG, "Text input is NULL");
         return;
     }
-    // Set up the text input
-    uart_text_input_set_header_text(app->text_input_ssid, "Enter SSID");
 
     // Initialize temp_buffer with existing SSID
     if (app->ssid && strlen(app->ssid) > 0)
@@ -854,8 +842,6 @@ static void web_crawler_setting_item_password_clicked(void *context, uint32_t in
         FURI_LOG_E(TAG, "Text input is NULL");
         return;
     }
-    // Set up the text input
-    uart_text_input_set_header_text(app->text_input_password, "Enter Password");
 
     // Initialize temp_buffer with existing password
     strncpy(app->temp_buffer_password, app->password, app->temp_buffer_size_password - 1);
@@ -899,8 +885,6 @@ static void web_crawler_setting_item_file_type_clicked(void *context, uint32_t i
         FURI_LOG_E(TAG, "Text input is NULL");
         return;
     }
-    // Set up the text input
-    uart_text_input_set_header_text(app->text_input_file_type, "Enter File Type");
 
     // Initialize temp_buffer with existing file_type
     if (app->file_type && strlen(app->file_type) > 0)
@@ -952,8 +936,6 @@ static void web_crawler_setting_item_file_rename_clicked(void *context, uint32_t
         FURI_LOG_E(TAG, "Text input is NULL");
         return;
     }
-    // Set up the text input
-    uart_text_input_set_header_text(app->text_input_file_rename, "Enter File Rename");
 
     // Initialize temp_buffer with existing file_rename
     if (app->file_rename && strlen(app->file_rename) > 0)

+ 1 - 11
web_crawler_e.h

@@ -2,17 +2,7 @@
 #ifndef WEB_CRAWLER_E
 #define WEB_CRAWLER_E
 
-#include <furi.h>
-#include <furi_hal.h>
-#include <gui/gui.h>
-#include <gui/view.h>
-#include <gui/view_dispatcher.h>
-#include <gui/modules/submenu.h>
-#include <gui/modules/widget.h>
-#include <gui/modules/text_box.h>
-#include <gui/modules/text_input.h>
-#include <gui/modules/variable_item_list.h>
-#include <dialogs/dialogs.h>
+#include <easy_flipper.h>
 #include <storage/storage.h>
 
 #define TAG "WebCrawler"

+ 86 - 258
web_crawler_i.h

@@ -9,251 +9,142 @@ WebCrawlerApp *web_crawler_app_alloc()
 {
     // Initialize the entire structure to zero to prevent undefined behavior
     WebCrawlerApp *app = (WebCrawlerApp *)malloc(sizeof(WebCrawlerApp));
-    if (!app)
-    {
-        FURI_LOG_E(TAG, "Failed to allocate WebCrawlerApp");
-        return NULL;
-    }
-    memset(app, 0, sizeof(WebCrawlerApp));
 
     // Open GUI
     Gui *gui = furi_record_open(RECORD_GUI);
-    if (!gui)
-    {
-        FURI_LOG_E(TAG, "Failed to open GUI record");
-        free_resources(app);
-        return NULL;
-    }
 
-    // Allocate ViewDispatcher
-    app->view_dispatcher = view_dispatcher_alloc();
-    if (!app->view_dispatcher)
+    // Initialize UART with the correct callback
+    if (!flipper_http_init(flipper_http_rx_callback, app))
     {
-        FURI_LOG_E(TAG, "Failed to allocate ViewDispatcher");
-        furi_record_close(RECORD_GUI);
-        free(app);
+        FURI_LOG_E(TAG, "Failed to initialize UART");
         return NULL;
     }
 
-    // Attach ViewDispatcher to GUI
-    view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
-    view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
-
-    // Initialize UART with the correct callback
-    if (!flipper_http_init(flipper_http_rx_callback, app))
+    // Allocate ViewDispatcher
+    if (!easy_flipper_set_view_dispatcher(&app->view_dispatcher, gui, app))
     {
-        FURI_LOG_E(TAG, "Failed to initialize UART");
         return NULL;
     }
 
     // Allocate and initialize temp_buffer and path
     app->temp_buffer_size_path = 128;
-    app->temp_buffer_path = malloc(app->temp_buffer_size_path);
-    if (!app->temp_buffer_path)
+    app->temp_buffer_size_ssid = 64;
+    app->temp_buffer_size_password = 64;
+    app->temp_buffer_size_file_type = 16;
+    app->temp_buffer_size_file_rename = 128;
+    app->temp_buffer_size_http_method = 8;
+    app->temp_buffer_size_headers = 256;
+    app->temp_buffer_size_payload = 256;
+    if (!easy_flipper_set_buffer(&app->temp_buffer_path, app->temp_buffer_size_path))
     {
-        FURI_LOG_E(TAG, "Failed to allocate temp_buffer_path");
-        free_all(app, "Failed to allocate temp_buffer_path");
         return NULL;
     }
-    app->temp_buffer_path[0] = '\0';
-
-    // Allocate path
-    app->path = malloc(app->temp_buffer_size_path);
-    if (!app->path)
+    if (!easy_flipper_set_buffer(&app->path, app->temp_buffer_size_path))
     {
-        FURI_LOG_E(TAG, "Failed to allocate path");
-        free_all(app, "Failed to allocate path");
         return NULL;
     }
-    app->path[0] = '\0';
-
-    // Allocate and initialize temp_buffer_ssid
-    app->temp_buffer_size_ssid = 128;
-    app->temp_buffer_ssid = malloc(app->temp_buffer_size_ssid);
-    if (!app->temp_buffer_ssid)
+    if (!easy_flipper_set_buffer(&app->temp_buffer_ssid, app->temp_buffer_size_ssid))
     {
-        FURI_LOG_E(TAG, "Failed to allocate temp_buffer_ssid");
-        free_all(app, "Failed to allocate temp_buffer_ssid");
         return NULL;
     }
-    app->temp_buffer_ssid[0] = '\0';
-
-    // Allocate ssid
-    app->ssid = malloc(app->temp_buffer_size_ssid);
-    if (!app->ssid)
+    if (!easy_flipper_set_buffer(&app->ssid, app->temp_buffer_size_ssid))
     {
-        FURI_LOG_E(TAG, "Failed to allocate ssid");
-        free_all(app, "Failed to allocate ssid");
         return NULL;
     }
-    app->ssid[0] = '\0';
-
-    // Allocate and initialize temp_buffer_password
-    app->temp_buffer_size_password = 128;
-    app->temp_buffer_password = malloc(app->temp_buffer_size_password);
-    if (!app->temp_buffer_password)
+    if (!easy_flipper_set_buffer(&app->temp_buffer_password, app->temp_buffer_size_password))
     {
-        FURI_LOG_E(TAG, "Failed to allocate temp_buffer_password");
-        free_all(app, "Failed to allocate temp_buffer_password");
         return NULL;
     }
-    app->temp_buffer_password[0] = '\0';
-
-    // Allocate password
-    app->password = malloc(app->temp_buffer_size_password);
-    if (!app->password)
+    if (!easy_flipper_set_buffer(&app->password, app->temp_buffer_size_password))
     {
-        FURI_LOG_E(TAG, "Failed to allocate password");
-        free_all(app, "Failed to allocate password");
         return NULL;
     }
-    app->password[0] = '\0';
-
-    // Allocate and initialize temp_buffer_file_type
-    app->temp_buffer_size_file_type = 128;
-    app->temp_buffer_file_type = malloc(app->temp_buffer_size_file_type);
-    if (!app->temp_buffer_file_type)
+    if (!easy_flipper_set_buffer(&app->temp_buffer_file_type, app->temp_buffer_size_file_type))
     {
-        FURI_LOG_E(TAG, "Failed to allocate temp_buffer_file_type");
-        free_all(app, "Failed to allocate temp_buffer_file_type");
         return NULL;
     }
-
-    // Allocate file_type
-    app->file_type = malloc(app->temp_buffer_size_file_type);
-    if (!app->file_type)
+    if (!easy_flipper_set_buffer(&app->file_type, app->temp_buffer_size_file_type))
     {
-        FURI_LOG_E(TAG, "Failed to allocate file_type");
-        free_all(app, "Failed to allocate file_type");
         return NULL;
     }
-    app->file_type[0] = '\0';
-
-    // Allocate and intialize temp_buffer_file_rename
-    app->temp_buffer_size_file_rename = 128;
-    app->temp_buffer_file_rename = malloc(app->temp_buffer_size_file_rename);
-    if (!app->temp_buffer_file_rename)
+    if (!easy_flipper_set_buffer(&app->temp_buffer_file_rename, app->temp_buffer_size_file_rename))
     {
-        FURI_LOG_E(TAG, "Failed to allocate temp_buffer_file_rename");
-        free_all(app, "Failed to allocate temp_buffer_file_rename");
         return NULL;
     }
-
-    // Allocate file_rename
-    app->file_rename = malloc(app->temp_buffer_size_file_rename);
-    if (!app->file_rename)
+    if (!easy_flipper_set_buffer(&app->file_rename, app->temp_buffer_size_file_rename))
     {
-        FURI_LOG_E(TAG, "Failed to allocate file_rename");
-        free_all(app, "Failed to allocate file_rename");
         return NULL;
     }
-    app->file_rename[0] = '\0';
-
-    // Allocate and initialize temp_buffer_http_method
-    app->temp_buffer_size_http_method = 128;
-    app->temp_buffer_http_method = malloc(app->temp_buffer_size_http_method);
-    if (!app->temp_buffer_http_method)
+    if (!easy_flipper_set_buffer(&app->temp_buffer_http_method, app->temp_buffer_size_http_method))
     {
-        FURI_LOG_E(TAG, "Failed to allocate temp_buffer_http_method");
-        free_all(app, "Failed to allocate temp_buffer_http_method");
         return NULL;
     }
-
-    // Allocate http_method
-    app->http_method = malloc(app->temp_buffer_size_http_method);
-    if (!app->http_method)
+    if (!easy_flipper_set_buffer(&app->http_method, app->temp_buffer_size_http_method))
     {
-        FURI_LOG_E(TAG, "Failed to allocate http_method");
-        free_all(app, "Failed to allocate http_method");
         return NULL;
     }
-
-    // Allocate and initialize temp_buffer_headers
-    app->temp_buffer_size_headers = 256;
-    app->temp_buffer_headers = malloc(app->temp_buffer_size_headers);
-    if (!app->temp_buffer_headers)
+    if (!easy_flipper_set_buffer(&app->temp_buffer_headers, app->temp_buffer_size_headers))
     {
-        FURI_LOG_E(TAG, "Failed to allocate temp_buffer_headers");
-        free_all(app, "Failed to allocate temp_buffer_headers");
         return NULL;
     }
-
-    // Allocate headers
-    app->headers = malloc(app->temp_buffer_size_headers);
-    if (!app->headers)
+    if (!easy_flipper_set_buffer(&app->headers, app->temp_buffer_size_headers))
     {
-        FURI_LOG_E(TAG, "Failed to allocate headers");
-        free_all(app, "Failed to allocate headers");
         return NULL;
     }
-
-    // Allocate and initialize temp_buffer_payload
-    app->temp_buffer_size_payload = 128;
-    app->temp_buffer_payload = malloc(app->temp_buffer_size_payload);
-    if (!app->temp_buffer_payload)
+    if (!easy_flipper_set_buffer(&app->temp_buffer_payload, app->temp_buffer_size_payload))
     {
-        FURI_LOG_E(TAG, "Failed to allocate temp_buffer_payload");
-        free_all(app, "Failed to allocate temp_buffer_payload");
         return NULL;
     }
-
-    // Allocate payload
-    app->payload = malloc(app->temp_buffer_size_payload);
-    if (!app->payload)
+    if (!easy_flipper_set_buffer(&app->payload, app->temp_buffer_size_payload))
     {
-        FURI_LOG_E(TAG, "Failed to allocate payload");
-        free_all(app, "Failed to allocate payload");
         return NULL;
     }
 
     // Allocate TextInput views
-    app->text_input_path = uart_text_input_alloc();
-    app->text_input_ssid = uart_text_input_alloc();
-    app->text_input_password = uart_text_input_alloc();
-    app->text_input_file_type = uart_text_input_alloc();
-    app->text_input_file_rename = uart_text_input_alloc();
-    app->text_input_headers = uart_text_input_alloc();
-    app->text_input_payload = uart_text_input_alloc();
-    if (!app->text_input_path || !app->text_input_ssid || !app->text_input_password || !app->text_input_file_type || !app->text_input_file_rename || !app->text_input_headers || !app->text_input_payload)
+    if (!easy_flipper_set_uart_text_input(&app->text_input_path, WebCrawlerViewTextInput, "Enter URL", app->temp_buffer_path, app->temp_buffer_size_path, NULL, web_crawler_back_to_request_callback, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_ssid, WebCrawlerViewTextInputSSID, "Enter SSID", app->temp_buffer_ssid, app->temp_buffer_size_ssid, NULL, web_crawler_back_to_wifi_callback, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_password, WebCrawlerViewTextInputPassword, "Enter Password", app->temp_buffer_password, app->temp_buffer_size_password, NULL, web_crawler_back_to_wifi_callback, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_file_type, WebCrawlerViewTextInputFileType, "Enter File Type", app->temp_buffer_file_type, app->temp_buffer_size_file_type, NULL, web_crawler_back_to_file_callback, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_file_rename, WebCrawlerViewTextInputFileRename, "Enter File Rename", app->temp_buffer_file_rename, app->temp_buffer_size_file_rename, NULL, web_crawler_back_to_file_callback, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_headers, WebCrawlerViewTextInputHeaders, "Enter Headers", app->temp_buffer_headers, app->temp_buffer_size_headers, NULL, web_crawler_back_to_request_callback, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_payload, WebCrawlerViewTextInputPayload, "Enter Payload", app->temp_buffer_payload, app->temp_buffer_size_payload, NULL, web_crawler_back_to_request_callback, &app->view_dispatcher, app))
     {
-        FURI_LOG_E(TAG, "Failed to allocate TextInput");
-        free_all(app, "Failed to allocate TextInput");
         return NULL;
     }
 
-    // Add TextInput views with unique view IDs
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewTextInput, uart_text_input_get_view(app->text_input_path));
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewTextInputSSID, uart_text_input_get_view(app->text_input_ssid));
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewTextInputPassword, uart_text_input_get_view(app->text_input_password));
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewTextInputFileType, uart_text_input_get_view(app->text_input_file_type));
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewTextInputFileRename, uart_text_input_get_view(app->text_input_file_rename));
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewTextInputHeaders, uart_text_input_get_view(app->text_input_headers));
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewTextInputPayload, uart_text_input_get_view(app->text_input_payload));
-
-    // Set previous callback for TextInput views to return to Configure screen
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_path), web_crawler_back_to_request_callback);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_headers), web_crawler_back_to_request_callback);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_payload), web_crawler_back_to_request_callback);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_ssid), web_crawler_back_to_wifi_callback);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_password), web_crawler_back_to_wifi_callback);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_file_type), web_crawler_back_to_file_callback);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_file_rename), web_crawler_back_to_file_callback);
-
-    // Allocate Configuration screen
-    app->variable_item_list_wifi = variable_item_list_alloc();
-    app->variable_item_list_file = variable_item_list_alloc();
-    app->variable_item_list_request = variable_item_list_alloc();
-    if (!app->variable_item_list_wifi || !app->variable_item_list_file || !app->variable_item_list_request)
+    // Allocate VariableItemList views
+    if (!easy_flipper_set_variable_item_list(&app->variable_item_list_wifi, WebCrawlerViewVariableItemListWifi, web_crawler_wifi_enter_callback, web_crawler_back_to_configure_callback, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_variable_item_list(&app->variable_item_list_file, WebCrawlerViewVariableItemListFile, web_crawler_file_enter_callback, web_crawler_back_to_configure_callback, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_variable_item_list(&app->variable_item_list_request, WebCrawlerViewVariableItemListRequest, web_crawler_request_enter_callback, web_crawler_back_to_configure_callback, &app->view_dispatcher, app))
     {
-        FURI_LOG_E(TAG, "Failed to allocate VariableItemList");
-        free_all(app, "Failed to allocate VariableItemList");
         return NULL;
     }
-    variable_item_list_reset(app->variable_item_list_wifi);
-    variable_item_list_reset(app->variable_item_list_file);
-    variable_item_list_reset(app->variable_item_list_request);
 
-    // Add item to the configuration screen
+    // set variable items
     app->path_item = variable_item_list_add(app->variable_item_list_request, "Path", 0, NULL, NULL);
     app->http_method_item = variable_item_list_add(app->variable_item_list_request, "HTTP Method", 4, web_crawler_http_method_change, app);
     app->headers_item = variable_item_list_add(app->variable_item_list_request, "Headers", 0, NULL, NULL);
@@ -284,37 +175,17 @@ WebCrawlerApp *web_crawler_app_alloc()
     variable_item_set_current_value_text(app->file_read_item, "");   // Initialize
     variable_item_set_current_value_text(app->file_delete_item, ""); // Initialize
 
-    // Set a single callback for all items
-    variable_item_list_set_enter_callback(app->variable_item_list_wifi, web_crawler_wifi_enter_callback, app);
-    view_set_previous_callback(variable_item_list_get_view(app->variable_item_list_wifi), web_crawler_back_to_configure_callback);
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewVariableItemListWifi, variable_item_list_get_view(app->variable_item_list_wifi));
-
-    variable_item_list_set_enter_callback(app->variable_item_list_file, web_crawler_file_enter_callback, app);
-    view_set_previous_callback(variable_item_list_get_view(app->variable_item_list_file), web_crawler_back_to_configure_callback);
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewVariableItemListFile, variable_item_list_get_view(app->variable_item_list_file));
-
-    variable_item_list_set_enter_callback(app->variable_item_list_request, web_crawler_request_enter_callback, app);
-    view_set_previous_callback(variable_item_list_get_view(app->variable_item_list_request), web_crawler_back_to_configure_callback);
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewVariableItemListRequest, variable_item_list_get_view(app->variable_item_list_request));
-    //------------------------------//
-    //        SUBMENU VIEW          //
-    //------------------------------//
-
-    // Allocate
-    app->submenu_main = submenu_alloc();
-    app->submenu_config = submenu_alloc();
-    if (!app->submenu_main || !app->submenu_config)
+    // Allocate Submenu views
+    if (!easy_flipper_set_submenu(&app->submenu_main, WebCrawlerViewSubmenuMain, "Web Crawler v0.5", web_crawler_exit_app_callback, &app->view_dispatcher))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_submenu(&app->submenu_config, WebCrawlerViewSubmenuConfig, "Settings", web_crawler_back_to_main_callback, &app->view_dispatcher))
     {
-        FURI_LOG_E(TAG, "Failed to allocate Submenu");
-        free_all(app, "Failed to allocate Submenu");
         return NULL;
     }
 
-    // Set header
-    submenu_set_header(app->submenu_main, "Web Crawler v0.4");
-    submenu_set_header(app->submenu_config, "Settings");
-
-    // Add items
+    // Add Submenu items
     submenu_add_item(app->submenu_main, "Run", WebCrawlerSubmenuIndexRun, web_crawler_submenu_callback, app);
     submenu_add_item(app->submenu_main, "About", WebCrawlerSubmenuIndexAbout, web_crawler_submenu_callback, app);
     submenu_add_item(app->submenu_main, "Settings", WebCrawlerSubmenuIndexConfig, web_crawler_submenu_callback, app);
@@ -323,72 +194,29 @@ WebCrawlerApp *web_crawler_app_alloc()
     submenu_add_item(app->submenu_config, "File", WebCrawlerSubmenuIndexFile, web_crawler_submenu_callback, app);
     submenu_add_item(app->submenu_config, "Request", WebCrawlerSubmenuIndexRequest, web_crawler_submenu_callback, app);
 
-    // Set previous callback for Submenu
-    view_set_previous_callback(submenu_get_view(app->submenu_main), web_crawler_exit_app_callback);       // Exit App
-    view_set_previous_callback(submenu_get_view(app->submenu_config), web_crawler_back_to_main_callback); // Back to Main
-
-    // Add Submenu view to ViewDispatcher
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewSubmenuMain, submenu_get_view(app->submenu_main));
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewSubmenuConfig, submenu_get_view(app->submenu_config));
-
-    //---------------------------------------------------------->
-
-    // Allocate Main view
-    app->view_main = view_alloc();
-    app->view_run = view_alloc();
-    if (!app->view_main || !app->view_run)
+    // Allocate views
+    if (!easy_flipper_set_view(&app->view_main, WebCrawlerViewMain, NULL, NULL, web_crawler_exit_app_callback, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_view(&app->view_run, WebCrawlerViewRun, web_crawler_view_draw_callback, NULL, web_crawler_back_to_main_callback, &app->view_dispatcher, app))
     {
-        free_all(app, "Failed to allocate Views");
         return NULL;
     }
-
-    // view_set_draw_callback(app->view_main, web_crawler_view_draw_callback);
-    view_set_previous_callback(app->view_main, web_crawler_exit_app_callback);
-
-    view_set_draw_callback(app->view_run, web_crawler_view_draw_callback);
-    view_set_previous_callback(app->view_run, web_crawler_back_to_main_callback);
-
-    // Add Main view to ViewDispatcher
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewMain, app->view_main);
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewRun, app->view_run);
 
     //-- WIDGET ABOUT VIEW --
-
-    // Allocate and add About view
-    app->widget_about = widget_alloc();
-    app->widget_file_read = widget_alloc();
-    app->widget_file_delete = widget_alloc();
-    if (!app->widget_about || !app->widget_file_read || !app->widget_file_delete)
+    if (!easy_flipper_set_widget(&app->widget_about, WebCrawlerViewAbout, "Web Crawler App\n---\nThis is a web crawler app for Flipper Zero.\n---\nVisit github.com/jblanked for more details.\n---\nPress BACK to return.", web_crawler_back_to_main_callback, &app->view_dispatcher))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_widget(&app->widget_file_read, WebCrawlerViewFileRead, "Data will be displayed here.", web_crawler_back_to_file_callback, &app->view_dispatcher))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_widget(&app->widget_file_delete, WebCrawlerViewFileDelete, "File deleted.", web_crawler_back_to_file_callback, &app->view_dispatcher))
     {
-        FURI_LOG_E(TAG, "Failed to allocate Widget");
-        free_all(app, "Failed to allocate Widget");
         return NULL;
     }
-
-    // Reset the widget before adding elements
-    widget_reset(app->widget_about);
-    widget_reset(app->widget_file_read);
-    widget_reset(app->widget_file_delete);
-
-    widget_add_text_scroll_element(app->widget_about, 0, 0, 128, 64, "Web Crawler App\n"
-                                                                     "---\n"
-                                                                     "This is a web crawler app for Flipper Zero.\n"
-                                                                     "---\n"
-                                                                     "Visit github.com/jblanked for more details.\n"
-                                                                     "---\n"
-                                                                     "Press BACK to return.");
-
-    widget_add_text_scroll_element(app->widget_file_read, 0, 0, 128, 64, "Data will be displayed here.");
-    widget_add_text_scroll_element(app->widget_file_delete, 0, 0, 128, 64, "File deleted.");
-
-    view_set_previous_callback(widget_get_view(app->widget_about), web_crawler_back_to_main_callback);
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewAbout, widget_get_view(app->widget_about));
-
-    view_set_previous_callback(widget_get_view(app->widget_file_read), web_crawler_back_to_file_callback);
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewFileRead, widget_get_view(app->widget_file_read));
-
-    view_set_previous_callback(widget_get_view(app->widget_file_delete), web_crawler_back_to_file_callback);
-    view_dispatcher_add_view(app->view_dispatcher, WebCrawlerViewFileDelete, widget_get_view(app->widget_file_delete));
 
     // Load Settings and Update Views
     if (!load_settings(