Explorar el Código

Check HTTP state and add Derek Jamison edits

jblanked hace 1 año
padre
commit
f403df8155

+ 11 - 0
alloc/flip_social_alloc.c

@@ -20,6 +20,17 @@ FlipSocialApp *flip_social_app_alloc()
     {
         return NULL;
     }
+    view_dispatcher_set_custom_event_callback(app->view_dispatcher, flip_social_custom_event_callback);
+    // Main view
+    if (!easy_flipper_set_view(&app->view_loader, FlipSocialViewLoader, flip_social_loader_draw_callback, NULL, flip_social_callback_to_submenu_logged_out, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    flip_social_loader_init(app->view_loader);
+    if (!easy_flipper_set_widget(&app->widget_result, FlipSocialViewWidgetResult, "Error, try again.", flip_social_callback_to_submenu_logged_out, &app->view_dispatcher))
+    {
+        return NULL;
+    }
 
     // Allocate the text input buffers
     app->wifi_ssid_logged_out_temp_buffer_size = MAX_USER_LENGTH;

+ 31 - 0
app.c

@@ -26,6 +26,37 @@ int32_t main_flip_social(void *p)
         return -1;
     }
 
+    // Thanks to Derek Jamison for the following edits
+    if (app_instance->wifi_ssid_logged_out != NULL &&
+        app_instance->wifi_password_logged_out != NULL)
+    {
+        // Try to wait for pong response.
+        uint8_t counter = 10;
+        while (fhttp.state == INACTIVE && --counter > 0)
+        {
+            FURI_LOG_D(TAG, "Waiting for PONG");
+            furi_delay_ms(100);
+        }
+
+        if (counter == 0)
+        {
+            DialogsApp *dialogs = furi_record_open(RECORD_DIALOGS);
+            DialogMessage *message = dialog_message_alloc();
+            dialog_message_set_header(
+                message, "[FlipperHTTP Error]", 64, 0, AlignCenter, AlignTop);
+            dialog_message_set_text(
+                message,
+                "Ensure your WiFi Developer\nBoard or Pico W is connected\nand the latest FlipperHTTP\nfirmware is installed.",
+                0,
+                63,
+                AlignLeft,
+                AlignBottom);
+            dialog_message_show(dialogs, message);
+            dialog_message_free(message);
+            furi_record_close(RECORD_DIALOGS);
+        }
+    }
+
     // Run the view dispatcher
     view_dispatcher_run(app_instance->view_dispatcher);
 

+ 528 - 1
callback/flip_social_callback.c

@@ -1,5 +1,68 @@
 #include <callback/flip_social_callback.h>
 
+// Below added by Derek Jamison
+// FURI_LOG_DEV will log only during app development. Be sure that Settings/System/Log Device is "LPUART"; so we dont use serial port.
+#ifdef DEVELOPMENT
+#define FURI_LOG_DEV(tag, format, ...) furi_log_print_format(FuriLogLevelInfo, tag, format, ##__VA_ARGS__)
+#define DEV_CRASH() furi_crash()
+#else
+#define FURI_LOG_DEV(tag, format, ...)
+#define DEV_CRASH()
+#endif
+
+static void flip_social_request_error_draw(Canvas *canvas)
+{
+    if (canvas == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_request_error_draw - canvas is NULL");
+        DEV_CRASH();
+        return;
+    }
+    if (fhttp.last_response != NULL)
+    {
+        if (strstr(fhttp.last_response, "[ERROR] Not connected to Wifi. Failed to reconnect.") != NULL)
+        {
+            canvas_clear(canvas);
+            canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
+            canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
+            canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
+        }
+        else if (strstr(fhttp.last_response, "[ERROR] Failed to connect to Wifi.") != NULL)
+        {
+            canvas_clear(canvas);
+            canvas_draw_str(canvas, 0, 10, "[ERROR] Not connected to Wifi.");
+            canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
+            canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
+        }
+        else if (strstr(fhttp.last_response, "[ERROR] GET request failed or returned empty data.") != NULL)
+        {
+            canvas_clear(canvas);
+            canvas_draw_str(canvas, 0, 10, "[ERROR] WiFi error.");
+            canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
+            canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
+        }
+        else if (strstr(fhttp.last_response, "[PONG]") != NULL)
+        {
+            canvas_clear(canvas);
+            canvas_draw_str(canvas, 0, 10, "[STATUS]Connecting to AP...");
+        }
+        else
+        {
+            canvas_clear(canvas);
+            FURI_LOG_E(TAG, "Received an error: %s", fhttp.last_response);
+            canvas_draw_str(canvas, 0, 10, "[ERROR] Unusual error...");
+            canvas_draw_str(canvas, 0, 60, "Press BACK and retry.");
+        }
+    }
+    else
+    {
+        canvas_clear(canvas);
+        canvas_draw_str(canvas, 0, 10, "[ERROR] Unknown error.");
+        canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
+        canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
+    }
+}
+
 /**
  * @brief Navigation callback to go back to the submenu Logged out.
  * @param context The context - unused
@@ -236,6 +299,11 @@ void flip_social_callback_submenu_choices(void *context, uint32_t index)
             &app->view_dispatcher);                      // view dispatcher
         break;
     case FlipSocialSubmenuLoggedInIndexFeed:
+        if (fhttp.state == INACTIVE)
+        {
+            FURI_LOG_E(TAG, "HTTP state is INACTIVE");
+            return;
+        }
         if (!easy_flipper_set_loading(&app->loading, FlipSocialViewLoading, flip_social_callback_to_submenu_logged_in, &app->view_dispatcher))
         {
             FURI_LOG_E(TAG, "Failed to set loading screen");
@@ -1118,4 +1186,463 @@ void flip_social_logged_in_messages_new_message_updated(void *context)
     }
     furi_timer_stop(fhttp.get_timeout_timer);
     view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedInMessagesSubmenu);
-}
+}
+
+static void flip_social_widget_set_text(char *message, Widget **widget)
+{
+    if (widget == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_set_widget_text - widget is NULL");
+        DEV_CRASH();
+        return;
+    }
+    if (message == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_set_widget_text - message is NULL");
+        DEV_CRASH();
+        return;
+    }
+    widget_reset(*widget);
+
+    uint32_t message_length = strlen(message); // Length of the message
+    uint32_t i = 0;                            // Index tracker
+    uint32_t formatted_index = 0;              // Tracker for where we are in the formatted message
+    char *formatted_message;                   // Buffer to hold the final formatted message
+
+    // Allocate buffer with double the message length plus one for safety
+    if (!easy_flipper_set_buffer(&formatted_message, message_length * 2 + 1))
+    {
+        return;
+    }
+
+    while (i < message_length)
+    {
+        uint32_t max_line_length = 31;                  // Maximum characters per line
+        uint32_t remaining_length = message_length - i; // Remaining characters
+        uint32_t line_length = (remaining_length < max_line_length) ? remaining_length : max_line_length;
+
+        // Check for newline character within the current segment
+        uint32_t newline_pos = i;
+        bool found_newline = false;
+        for (; newline_pos < i + line_length && newline_pos < message_length; newline_pos++)
+        {
+            if (message[newline_pos] == '\n')
+            {
+                found_newline = true;
+                break;
+            }
+        }
+
+        if (found_newline)
+        {
+            // If newline found, set line_length up to the newline
+            line_length = newline_pos - i;
+        }
+
+        // Temporary buffer to hold the current line
+        char line[32];
+        strncpy(line, message + i, line_length);
+        line[line_length] = '\0';
+
+        // If newline was found, skip it for the next iteration
+        if (found_newline)
+        {
+            i += line_length + 1; // +1 to skip the '\n' character
+        }
+        else
+        {
+            // Check if the line ends in the middle of a word and adjust accordingly
+            if (line_length == max_line_length && message[i + line_length] != '\0' && message[i + line_length] != ' ')
+            {
+                // Find the last space within the current line to avoid breaking a word
+                char *last_space = strrchr(line, ' ');
+                if (last_space != NULL)
+                {
+                    // Adjust the line_length to avoid cutting the word
+                    line_length = last_space - line;
+                    line[line_length] = '\0'; // Null-terminate at the space
+                }
+            }
+
+            // Move the index forward by the determined line_length
+            i += line_length;
+
+            // Skip any spaces at the beginning of the next line
+            while (i < message_length && message[i] == ' ')
+            {
+                i++;
+            }
+        }
+
+        // Manually copy the fixed line into the formatted_message buffer
+        for (uint32_t j = 0; j < line_length; j++)
+        {
+            formatted_message[formatted_index++] = line[j];
+        }
+
+        // Add a newline character for line spacing
+        formatted_message[formatted_index++] = '\n';
+    }
+
+    // Null-terminate the formatted_message
+    formatted_message[formatted_index] = '\0';
+
+    // Add the formatted message to the widget
+    widget_add_text_scroll_element(*widget, 0, 0, 128, 64, formatted_message);
+}
+
+void flip_social_loader_draw_callback(Canvas *canvas, void *model)
+{
+    if (!canvas || !model)
+    {
+        FURI_LOG_E(TAG, "flip_social_loader_draw_callback - canvas or model is NULL");
+        return;
+    }
+
+    SerialState http_state = fhttp.state;
+    DataLoaderModel *data_loader_model = (DataLoaderModel *)model;
+    DataState data_state = data_loader_model->data_state;
+    char *title = data_loader_model->title;
+
+    canvas_set_font(canvas, FontSecondary);
+
+    if (http_state == INACTIVE)
+    {
+        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;
+    }
+
+    if (data_state == DataStateError || data_state == DataStateParseError)
+    {
+        flip_social_request_error_draw(canvas);
+        return;
+    }
+
+    canvas_draw_str(canvas, 0, 7, title);
+    canvas_draw_str(canvas, 0, 17, "Loading...");
+
+    if (data_state == DataStateInitial)
+    {
+        return;
+    }
+
+    if (http_state == SENDING)
+    {
+        canvas_draw_str(canvas, 0, 27, "Sending...");
+        return;
+    }
+
+    if (http_state == RECEIVING || data_state == DataStateRequested)
+    {
+        canvas_draw_str(canvas, 0, 27, "Receiving...");
+        return;
+    }
+
+    if (http_state == IDLE && data_state == DataStateReceived)
+    {
+        canvas_draw_str(canvas, 0, 27, "Processing...");
+        return;
+    }
+
+    if (http_state == IDLE && data_state == DataStateParsed)
+    {
+        canvas_draw_str(canvas, 0, 27, "Processed...");
+        return;
+    }
+}
+
+static void flip_social_loader_process_callback(void *context)
+{
+    if (context == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_loader_process_callback - context is NULL");
+        DEV_CRASH();
+        return;
+    }
+
+    FlipSocialApp *app = (FlipSocialApp *)context;
+    View *view = app->view_loader;
+
+    DataState current_data_state;
+    with_view_model(view, DataLoaderModel * model, { current_data_state = model->data_state; }, false);
+
+    if (current_data_state == DataStateInitial)
+    {
+        with_view_model(
+            view,
+            DataLoaderModel * model,
+            {
+                model->data_state = DataStateRequested;
+                DataLoaderFetch fetch = model->fetcher;
+                if (fetch == NULL)
+                {
+                    FURI_LOG_E(TAG, "Model doesn't have Fetch function assigned.");
+                    model->data_state = DataStateError;
+                    return;
+                }
+
+                // Clear any previous responses
+                strncpy(fhttp.last_response, "", 1);
+                bool request_status = fetch(model);
+                if (!request_status)
+                {
+                    model->data_state = DataStateError;
+                }
+            },
+            true);
+    }
+    else if (current_data_state == DataStateRequested || current_data_state == DataStateError)
+    {
+        if (fhttp.state == IDLE && fhttp.last_response != NULL)
+        {
+            if (strstr(fhttp.last_response, "[PONG]") != NULL)
+            {
+                FURI_LOG_DEV(TAG, "PONG received.");
+            }
+            else if (strncmp(fhttp.last_response, "[SUCCESS]", 9) == 0)
+            {
+                FURI_LOG_DEV(TAG, "SUCCESS received. %s", fhttp.last_response ? fhttp.last_response : "NULL");
+            }
+            else if (strncmp(fhttp.last_response, "[ERROR]", 9) == 0)
+            {
+                FURI_LOG_DEV(TAG, "ERROR received. %s", fhttp.last_response ? fhttp.last_response : "NULL");
+            }
+            else if (strlen(fhttp.last_response) == 0)
+            {
+                // Still waiting on response
+            }
+            else
+            {
+                with_view_model(view, DataLoaderModel * model, { model->data_state = DataStateReceived; }, true);
+            }
+        }
+        else if (fhttp.state == SENDING || fhttp.state == RECEIVING)
+        {
+            // continue waiting
+        }
+        else if (fhttp.state == INACTIVE)
+        {
+            // inactive. try again
+        }
+        else if (fhttp.state == ISSUE)
+        {
+            with_view_model(view, DataLoaderModel * model, { model->data_state = DataStateError; }, true);
+        }
+        else
+        {
+            FURI_LOG_DEV(TAG, "Unexpected state: %d lastresp: %s", fhttp.state, fhttp.last_response ? fhttp.last_response : "NULL");
+            DEV_CRASH();
+        }
+    }
+    else if (current_data_state == DataStateReceived)
+    {
+        with_view_model(
+            view,
+            DataLoaderModel * model,
+            {
+                char *data_text;
+                if (model->parser == NULL)
+                {
+                    data_text = NULL;
+                    FURI_LOG_DEV(TAG, "Parser is NULL");
+                    DEV_CRASH();
+                }
+                else
+                {
+                    data_text = model->parser(model);
+                }
+                FURI_LOG_DEV(TAG, "Parsed data: %s\r\ntext: %s", fhttp.last_response ? fhttp.last_response : "NULL", data_text ? data_text : "NULL");
+                model->data_text = data_text;
+                if (data_text == NULL)
+                {
+                    model->data_state = DataStateParseError;
+                }
+                else
+                {
+                    model->data_state = DataStateParsed;
+                }
+            },
+            true);
+    }
+    else if (current_data_state == DataStateParsed)
+    {
+        with_view_model(
+            view,
+            DataLoaderModel * model,
+            {
+                if (++model->request_index < model->request_count)
+                {
+                    model->data_state = DataStateInitial;
+                }
+                else
+                {
+                    flip_social_widget_set_text(model->data_text != NULL ? model->data_text : "Empty result", &app_instance->widget_result);
+                    if (model->data_text != NULL)
+                    {
+                        free(model->data_text);
+                        model->data_text = NULL;
+                    }
+                    view_set_previous_callback(widget_get_view(app_instance->widget_result), model->back_callback);
+                    view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewWidgetResult);
+                }
+            },
+            true);
+    }
+}
+
+static void flip_social_loader_timer_callback(void *context)
+{
+    if (context == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_loader_timer_callback - context is NULL");
+        DEV_CRASH();
+        return;
+    }
+    FlipSocialApp *app = (FlipSocialApp *)context;
+    view_dispatcher_send_custom_event(app->view_dispatcher, FlipSocialCustomEventProcess);
+}
+
+static void flip_social_loader_on_enter(void *context)
+{
+    if (context == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_loader_on_enter - context is NULL");
+        DEV_CRASH();
+        return;
+    }
+    FlipSocialApp *app = (FlipSocialApp *)context;
+    View *view = app->view_loader;
+    with_view_model(
+        view,
+        DataLoaderModel * model,
+        {
+            view_set_previous_callback(view, model->back_callback);
+            if (model->timer == NULL)
+            {
+                model->timer = furi_timer_alloc(flip_social_loader_timer_callback, FuriTimerTypePeriodic, app);
+            }
+            furi_timer_start(model->timer, 250);
+        },
+        true);
+}
+
+static void flip_social_loader_on_exit(void *context)
+{
+    if (context == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_loader_on_exit - context is NULL");
+        DEV_CRASH();
+        return;
+    }
+    FlipSocialApp *app = (FlipSocialApp *)context;
+    View *view = app->view_loader;
+    with_view_model(
+        view,
+        DataLoaderModel * model,
+        {
+            if (model->timer)
+            {
+                furi_timer_stop(model->timer);
+            }
+        },
+        false);
+}
+
+void flip_social_loader_init(View *view)
+{
+    if (view == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_loader_init - view is NULL");
+        DEV_CRASH();
+        return;
+    }
+    view_allocate_model(view, ViewModelTypeLocking, sizeof(DataLoaderModel));
+    view_set_enter_callback(view, flip_social_loader_on_enter);
+    view_set_exit_callback(view, flip_social_loader_on_exit);
+}
+
+void flip_social_loader_free_model(View *view)
+{
+    if (view == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_loader_free_model - view is NULL");
+        DEV_CRASH();
+        return;
+    }
+    with_view_model(
+        view,
+        DataLoaderModel * model,
+        {
+            if (model->timer)
+            {
+                furi_timer_free(model->timer);
+                model->timer = NULL;
+            }
+            if (model->parser_context)
+            {
+                free(model->parser_context);
+                model->parser_context = NULL;
+            }
+        },
+        false);
+}
+
+bool flip_social_custom_event_callback(void *context, uint32_t index)
+{
+    if (context == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_custom_event_callback - context is NULL");
+        DEV_CRASH();
+        return false;
+    }
+
+    switch (index)
+    {
+    case FlipSocialCustomEventProcess:
+        flip_social_loader_process_callback(context);
+        return true;
+    default:
+        FURI_LOG_DEV(TAG, "flip_social_custom_event_callback. Unknown index: %ld", index);
+        return false;
+    }
+}
+
+void flip_social_generic_switch_to_view(FlipSocialApp *app, char *title, DataLoaderFetch fetcher, DataLoaderParser parser, size_t request_count, ViewNavigationCallback back, uint32_t view_id)
+{
+    if (app == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_generic_switch_to_view - app is NULL");
+        DEV_CRASH();
+        return;
+    }
+
+    View *view = app->view_loader;
+    if (view == NULL)
+    {
+        FURI_LOG_E(TAG, "flip_social_generic_switch_to_view - view is NULL");
+        DEV_CRASH();
+        return;
+    }
+
+    with_view_model(
+        view,
+        DataLoaderModel * model,
+        {
+            model->title = title;
+            model->fetcher = fetcher;
+            model->parser = parser;
+            model->request_index = 0;
+            model->request_count = request_count;
+            model->back_callback = back;
+            model->data_state = DataStateInitial;
+            model->data_text = NULL;
+        },
+        true);
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, view_id);
+}

+ 44 - 0
callback/flip_social_callback.h

@@ -253,4 +253,48 @@ void flip_social_logged_in_messages_new_message_updated(void *context);
  */
 void flip_social_text_input_logged_out_register_item_selected(void *context, uint32_t index);
 
+// Add edits by Derek Jamison
+typedef enum DataState DataState;
+enum DataState
+{
+    DataStateInitial,
+    DataStateRequested,
+    DataStateReceived,
+    DataStateParsed,
+    DataStateParseError,
+    DataStateError,
+};
+
+typedef enum FlipSocialCustomEvent FlipSocialCustomEvent;
+enum FlipSocialCustomEvent
+{
+    FlipSocialCustomEventProcess,
+};
+
+typedef struct DataLoaderModel DataLoaderModel;
+typedef bool (*DataLoaderFetch)(DataLoaderModel *model);
+typedef char *(*DataLoaderParser)(DataLoaderModel *model);
+struct DataLoaderModel
+{
+    char *title;
+    char *data_text;
+    DataState data_state;
+    DataLoaderFetch fetcher;
+    DataLoaderParser parser;
+    void *parser_context;
+    size_t request_index;
+    size_t request_count;
+    ViewNavigationCallback back_callback;
+    FuriTimer *timer;
+};
+void flip_social_generic_switch_to_view(FlipSocialApp *app, char *title, DataLoaderFetch fetcher, DataLoaderParser parser, size_t request_count, ViewNavigationCallback back, uint32_t view_id);
+
+void flip_social_loader_draw_callback(Canvas *canvas, void *model);
+
+void flip_social_loader_init(View *view);
+
+void flip_social_loader_free_model(View *view);
+
+bool flip_social_custom_event_callback(void *context, uint32_t index);
+
 #endif

+ 2 - 0
easy_flipper/easy_flipper.h

@@ -15,6 +15,8 @@
 #include <gui/modules/text_box.h>
 #include <gui/modules/variable_item_list.h>
 #include <gui/modules/dialog_ex.h>
+#include <notification/notification.h>
+#include <dialogs/dialogs.h>
 #include <gui/modules/popup.h>
 #include <gui/modules/loading.h>
 #include <text_input/uart_text_input.h>

+ 5 - 0
explore/flip_social_explore.c

@@ -45,6 +45,11 @@ void flip_social_free_explore()
 // as the feed is upgraded, then we can port more to the explore view
 bool flip_social_get_explore()
 {
+    if (fhttp.state == INACTIVE)
+    {
+        FURI_LOG_E(TAG, "HTTP state is INACTIVE");
+        return false;
+    }
     snprintf(
         fhttp.file_path,
         sizeof(fhttp.file_path),

+ 5 - 0
feed/flip_social_feed.c

@@ -7,6 +7,11 @@ bool flip_social_get_feed()
         FURI_LOG_E(TAG, "FlipSocialApp is NULL");
         return false;
     }
+    if (fhttp.state == INACTIVE)
+    {
+        FURI_LOG_E(TAG, "HTTP state is INACTIVE");
+        return false;
+    }
     // Get the feed from the server
     if (app_instance->login_username_logged_out == NULL)
     {

+ 13 - 0
flip_social.c

@@ -20,6 +20,8 @@ char *selected_message = NULL;
 
 char auth_headers[256] = {0};
 
+void flip_social_loader_free_model(View *view);
+
 /**
  * @brief Function to free the resources used by FlipSocialApp.
  * @details Cleans up all allocated resources before exiting the application.
@@ -186,8 +188,19 @@ void flip_social_app_free(FlipSocialApp *app)
         view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInSettingsAbout);
         widget_free(app->widget_logged_in_about);
     }
+    if (app->widget_result)
+    {
+        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewWidgetResult);
+        widget_free(app->widget_result);
+    }
 
     // Free View(s)
+    if (app->view_loader)
+    {
+        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoader);
+        flip_social_loader_free_model(app->view_loader);
+        view_free(app->view_loader);
+    }
     if (app->view_process_login)
     {
         view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedOutProcessLogin);

+ 6 - 0
flip_social.h

@@ -148,11 +148,17 @@ typedef enum
     FlipSocialViewLoggedInMessagesProcess, // The view after clicking on a user in the messages screen
     //
     FlipSocialViewLoading, // The loading screen
+    //
+    FlipSocialViewWidgetResult, // The text box that displays the random fact
+    FlipSocialViewLoader,       // The loader screen retrieves data from the internet
 } FlipSocialView;
 
 // Define the application structure
 typedef struct
 {
+    View *view_loader;
+    Widget *widget_result;
+    //
     ViewDispatcher *view_dispatcher;        // Switches between our views
     Submenu *submenu_logged_out;            // The application submenu (logged out)
     Submenu *submenu_logged_in;             // The application submenu (logged in)

+ 5 - 0
flipper_http/flipper_http.c

@@ -1508,6 +1508,11 @@ void flipper_http_loading_task(bool (*http_request)(void),
                                uint32_t failure_view_id,
                                ViewDispatcher **view_dispatcher)
 {
+    if (fhttp.state == INACTIVE)
+    {
+        view_dispatcher_switch_to_view(*view_dispatcher, failure_view_id);
+        return;
+    }
     Loading *loading;
     int32_t loading_view_id = 987654321; // Random ID
 

+ 5 - 0
friends/flip_social_friends.c

@@ -45,6 +45,11 @@ bool flip_social_get_friends()
         FURI_LOG_E(TAG, "App instance is NULL");
         return false;
     }
+    if (fhttp.state == INACTIVE)
+    {
+        FURI_LOG_E(TAG, "HTTP state is INACTIVE");
+        return false;
+    }
     // will return true unless the devboard is not connected
     char url[100];
     snprintf(

+ 10 - 0
messages/flip_social_messages.c

@@ -146,6 +146,11 @@ bool flip_social_get_message_users()
         FURI_LOG_E(TAG, "Username is NULL");
         return false;
     }
+    if (fhttp.state == INACTIVE)
+    {
+        FURI_LOG_E(TAG, "HTTP state is INACTIVE");
+        return false;
+    }
     char command[128];
     snprintf(
         fhttp.file_path,
@@ -168,6 +173,11 @@ bool flip_social_get_message_users()
 // Get all the messages between the logged in user and the selected user
 bool flip_social_get_messages_with_user()
 {
+    if (fhttp.state == INACTIVE)
+    {
+        FURI_LOG_E(TAG, "HTTP state is INACTIVE");
+        return false;
+    }
     if (app_instance->login_username_logged_out == NULL)
     {
         FURI_LOG_E(TAG, "Username is NULL");