Просмотр исходного кода

Merge pull request #4 from jblanked/dev_0.7

Update FlipSocial to 0.7
JBlanked 1 год назад
Родитель
Сommit
0863f66c5f

+ 13 - 11
README.md

@@ -46,21 +46,22 @@ FlipSocial uses the FlipperHTTP flash for the WiFi Devboard, first introduced in
 - Direct Messaging
 
 **v0.5**
-- Improved memory allocation
-- Improved Feed Page
+- Improve memory allocation
+- Improve Feed Page
 - Raspberry Pi Pico W Support
 
 **v0.6**
-- Improved memory allocation
-- Fixed bugs in Direct Messaging View
-- Fixed bugs in Pre-Save View
+- Improve memory allocation
+- Update the Direct Messaging View
+- Update the Pre-Save View
 
 **v0.7**
-- Improved User Profile (Bio, friend count, block)
-- Improved Explore Page
+- Improve memory allocation
+- Loading screens.
 
 **v0.8**
-- Create and Post Pixel Art
+- Improve User Profile (Bio, friend count, block)
+- Improve Explore Page
 
 **v1.0**
 - Official Release
@@ -88,8 +89,9 @@ This is a big project, and I welcome all contributors, especially developers int
 - **Solution 3:** Ensure your WiFi Devboard is plugged in, then restart your Flipper device.
 
 5. Out of memory when starting the app or after visiting the feed and post views back-to-back.
-- **Solution:** Restart your Flipper device.
+- **Solution 1:** Restart your Flipper device.
+- **Solution 2:** Update the app to version 0.7 (or higher).
 
-6. I can no longer access my Direct Messages.
+6. I can no longer access the Messages.
 - **Solution 1:** Uppdate the app to version 0.6.3 (or higher)
-- **Solution 2:** Click the logout button then login again.
+- **Solution 2:** Click the logout button then login again. Make sure your password is correct before clicking "Login".

+ 30 - 87
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;
@@ -165,30 +176,15 @@ FlipSocialApp *flip_social_app_alloc()
     }
 
     // Allocate Submenu(s)
-    if (!easy_flipper_set_submenu(&app->submenu_logged_out, FlipSocialViewLoggedOutSubmenu, "FlipSocial v0.6", flip_social_callback_exit_app, &app->view_dispatcher))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_submenu(&app->submenu_logged_in, FlipSocialViewLoggedInSubmenu, "FlipSocial v0.6", flip_social_callback_exit_app, &app->view_dispatcher))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_submenu(&app->submenu_compose, FlipSocialViewLoggedInCompose, "Create A Post", flip_social_callback_to_submenu_logged_in, &app->view_dispatcher))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_submenu(&app->submenu_explore, FlipSocialViewLoggedInExploreSubmenu, "Explore", flip_social_callback_to_submenu_logged_in, &app->view_dispatcher))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_submenu(&app->submenu_friends, FlipSocialViewLoggedInFriendsSubmenu, "Friends", flip_social_callback_to_profile_logged_in, &app->view_dispatcher))
+    if (!easy_flipper_set_submenu(&app->submenu_logged_out, FlipSocialViewLoggedOutSubmenu, "FlipSocial v0.7", flip_social_callback_exit_app, &app->view_dispatcher))
     {
         return NULL;
     }
-    if (!easy_flipper_set_submenu(&app->submenu_messages, FlipSocialViewLoggedInMessagesSubmenu, "Messages", flip_social_callback_to_submenu_logged_in, &app->view_dispatcher))
+    if (!easy_flipper_set_submenu(&app->submenu_logged_in, FlipSocialViewLoggedInSubmenu, "FlipSocial v0.7", flip_social_callback_exit_app, &app->view_dispatcher))
     {
         return NULL;
     }
+
     if (!easy_flipper_set_submenu(&app->submenu_messages_user_choices, FlipSocialViewLoggedInMessagesUserChoices, "Users", flip_social_callback_to_messages_logged_in, &app->view_dispatcher))
     {
         return NULL;
@@ -206,39 +202,6 @@ FlipSocialApp *flip_social_app_alloc()
     submenu_add_item(app->submenu_logged_in, "Profile", FlipSocialSubmenuLoggedInIndexProfile, flip_social_callback_submenu_choices, app);
     submenu_add_item(app->submenu_logged_in, "Settings", FlipSocialSubmenuLoggedInIndexSettings, flip_social_callback_submenu_choices, app);
     submenu_add_item(app->submenu_logged_in, "Sign Out", FlipSocialSubmenuLoggedInSignOutButton, flip_social_callback_submenu_choices, app);
-    //
-    submenu_add_item(app->submenu_compose, "Add Pre-Save", FlipSocialSubmenuComposeIndexAddPreSave, flip_social_callback_submenu_choices, app);
-    //
-
-    // Allocate View(s)
-    if (!easy_flipper_set_view(&app->view_process_login, FlipSocialViewLoggedOutProcessLogin, flip_social_callback_draw_login, NULL, flip_social_callback_to_login_logged_out, &app->view_dispatcher, app))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_view(&app->view_process_register, FlipSocialViewLoggedOutProcessRegister, flip_social_callback_draw_register, NULL, flip_social_callback_to_register_logged_out, &app->view_dispatcher, app))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_view(&app->view_process_feed, FlipSocialViewLoggedInFeed, flip_social_callback_draw_feed, NULL, flip_social_callback_to_submenu_logged_in, &app->view_dispatcher, app))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_view(&app->view_process_compose, FlipSocialViewLoggedInProcessCompose, flip_social_callback_draw_compose, NULL, flip_social_callback_to_compose_logged_in, &app->view_dispatcher, app))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_view(&app->view_process_explore, FlipSocialViewLoggedInExploreProccess, flip_social_callback_draw_explore, NULL, flip_social_callback_to_explore_logged_in, &app->view_dispatcher, app))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_view(&app->view_process_friends, FlipSocialViewLoggedInFriendsProcess, flip_social_callback_draw_friends, NULL, flip_social_callback_to_friends_logged_in, &app->view_dispatcher, app))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_view(&app->view_process_messages, FlipSocialViewLoggedInMessagesProcess, flip_social_callback_draw_messages, NULL, flip_social_callback_to_messages_logged_in, &app->view_dispatcher, app))
-    {
-        return NULL;
-    }
 
     // Setup Variable Item List(s)
     if (!easy_flipper_set_variable_item_list(&app->variable_item_list_logged_out_wifi_settings, FlipSocialViewLoggedOutWifiSettings, flip_social_text_input_logged_out_wifi_settings_item_selected, flip_social_callback_to_submenu_logged_out, &app->view_dispatcher, app))
@@ -266,27 +229,27 @@ FlipSocialApp *flip_social_app_alloc()
         return NULL;
     }
 
-    app->variable_item_logged_out_wifi_settings_ssid = variable_item_list_add(app->variable_item_list_logged_out_wifi_settings, "SSID", 1, NULL, NULL);
-    app->variable_item_logged_out_wifi_settings_password = variable_item_list_add(app->variable_item_list_logged_out_wifi_settings, "Password", 1, NULL, NULL);
+    app->variable_item_logged_out_wifi_settings_ssid = variable_item_list_add(app->variable_item_list_logged_out_wifi_settings, "SSID", 1, NULL, app);
+    app->variable_item_logged_out_wifi_settings_password = variable_item_list_add(app->variable_item_list_logged_out_wifi_settings, "Password", 1, NULL, app);
     //
-    app->variable_item_logged_out_login_username = variable_item_list_add(app->variable_item_list_logged_out_login, "Username", 1, NULL, NULL);
-    app->variable_item_logged_out_login_password = variable_item_list_add(app->variable_item_list_logged_out_login, "Password", 1, NULL, NULL);
-    app->variable_item_logged_out_login_button = variable_item_list_add(app->variable_item_list_logged_out_login, "Login", 0, NULL, NULL);
+    app->variable_item_logged_out_login_username = variable_item_list_add(app->variable_item_list_logged_out_login, "Username", 1, NULL, app);
+    app->variable_item_logged_out_login_password = variable_item_list_add(app->variable_item_list_logged_out_login, "Password", 1, NULL, app);
+    app->variable_item_logged_out_login_button = variable_item_list_add(app->variable_item_list_logged_out_login, "Login", 0, NULL, app);
     //
-    app->variable_item_logged_out_register_username = variable_item_list_add(app->variable_item_list_logged_out_register, "Username", 1, NULL, NULL);
-    app->variable_item_logged_out_register_password = variable_item_list_add(app->variable_item_list_logged_out_register, "Password", 1, NULL, NULL);
-    app->variable_item_logged_out_register_password_2 = variable_item_list_add(app->variable_item_list_logged_out_register, "Confirm Password", 1, NULL, NULL);
-    app->variable_item_logged_out_register_button = variable_item_list_add(app->variable_item_list_logged_out_register, "Register", 0, NULL, NULL);
+    app->variable_item_logged_out_register_username = variable_item_list_add(app->variable_item_list_logged_out_register, "Username", 1, NULL, app);
+    app->variable_item_logged_out_register_password = variable_item_list_add(app->variable_item_list_logged_out_register, "Password", 1, NULL, app);
+    app->variable_item_logged_out_register_password_2 = variable_item_list_add(app->variable_item_list_logged_out_register, "Confirm Password", 1, NULL, app);
+    app->variable_item_logged_out_register_button = variable_item_list_add(app->variable_item_list_logged_out_register, "Register", 0, NULL, app);
     //
-    app->variable_item_logged_in_profile_username = variable_item_list_add(app->variable_item_list_logged_in_profile, "Username", 0, NULL, NULL);
-    app->variable_item_logged_in_profile_change_password = variable_item_list_add(app->variable_item_list_logged_in_profile, "Change Password", 0, NULL, NULL);
-    app->variable_item_logged_in_profile_friends = variable_item_list_add(app->variable_item_list_logged_in_profile, "Friends", 0, NULL, NULL);
+    app->variable_item_logged_in_profile_username = variable_item_list_add(app->variable_item_list_logged_in_profile, "Username", 1, NULL, app);
+    app->variable_item_logged_in_profile_change_password = variable_item_list_add(app->variable_item_list_logged_in_profile, "Change Password", 1, NULL, app);
+    app->variable_item_logged_in_profile_friends = variable_item_list_add(app->variable_item_list_logged_in_profile, "Friends", 0, NULL, app);
     //
-    app->variable_item_logged_in_settings_about = variable_item_list_add(app->variable_item_list_logged_in_settings, "About", 0, NULL, NULL);
-    app->variable_item_logged_in_settings_wifi = variable_item_list_add(app->variable_item_list_logged_in_settings, "WiFi", 0, NULL, NULL);
+    app->variable_item_logged_in_settings_about = variable_item_list_add(app->variable_item_list_logged_in_settings, "About", 0, NULL, app);
+    app->variable_item_logged_in_settings_wifi = variable_item_list_add(app->variable_item_list_logged_in_settings, "WiFi", 0, NULL, app);
     //
-    app->variable_item_logged_in_wifi_settings_ssid = variable_item_list_add(app->variable_item_list_logged_in_settings_wifi, "SSID", 1, NULL, NULL);
-    app->variable_item_logged_in_wifi_settings_password = variable_item_list_add(app->variable_item_list_logged_in_settings_wifi, "Password", 1, NULL, NULL);
+    app->variable_item_logged_in_wifi_settings_ssid = variable_item_list_add(app->variable_item_list_logged_in_settings_wifi, "SSID", 1, NULL, app);
+    app->variable_item_logged_in_wifi_settings_password = variable_item_list_add(app->variable_item_list_logged_in_settings_wifi, "Password", 1, NULL, app);
 
     // Setup Text Input(s)
     if (!easy_flipper_set_uart_text_input(&app->text_input_logged_out_wifi_settings_ssid, FlipSocialViewLoggedOutWifiSettingsSSIDInput, "Enter SSID", app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_out_temp_buffer_size, flip_social_logged_out_wifi_settings_ssid_updated, flip_social_callback_to_wifi_settings_logged_out, &app->view_dispatcher, app))
@@ -344,26 +307,6 @@ FlipSocialApp *flip_social_app_alloc()
         return NULL;
     }
 
-    // Setup About(s)
-    if (!easy_flipper_set_widget(&app->widget_logged_out_about, FlipSocialViewLoggedOutAbout, "Welcome to FlipSocial\n---\nThe social media app for\nFlipper Zero, created by\nJBlanked: www.flipsocial.net\n---\nPress BACK to return.", flip_social_callback_to_submenu_logged_out, &app->view_dispatcher))
-    {
-        return NULL;
-    }
-    if (!easy_flipper_set_widget(&app->widget_logged_in_about, FlipSocialViewLoggedInSettingsAbout, "Welcome to FlipSocial\n---\nThe social media app for\nFlipper Zero, created by\nJBlanked: www.flipsocial.net\n---\nPress BACK to return.", flip_social_callback_to_settings_logged_in, &app->view_dispatcher))
-    {
-        return NULL;
-    }
-
-    // load the playlist
-    if (load_playlist(&app->pre_saved_messages))
-    {
-        // Update the playlist submenu
-        for (uint32_t i = 0; i < app->pre_saved_messages.count; i++)
-        {
-            submenu_add_item(app->submenu_compose, app->pre_saved_messages.messages[i], FlipSocialSubemnuComposeIndexStartIndex + i, flip_social_callback_submenu_choices, app);
-        }
-    }
-
     // Load the settings
     if (!load_settings(app->wifi_ssid_logged_out,
                        app->wifi_ssid_logged_out_temp_buffer_size,

+ 0 - 1
alloc/flip_social_alloc.h

@@ -3,7 +3,6 @@
 #include <flip_social.h>
 #include <callback/flip_social_callback.h>
 #include <flip_storage/flip_social_storage.h>
-#include <draw/flip_social_draw.h>
 
 /**
  * @brief Function to allocate resources for the FlipSocialApp.

+ 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);
 

+ 1 - 1
application.fam

@@ -9,6 +9,6 @@ App(
     fap_icon_assets="assets",
     fap_author="jblanked",
     fap_weburl="https://github.com/jblanked/FlipSocial",
-    fap_version="0.6.3",
+    fap_version="0.7",
     fap_description="Social media platform for the Flipper Zero.",
 )

+ 7 - 0
assets/CHANGELOG.md

@@ -1,3 +1,10 @@
+## 0.7
+- Improved memory allocation
+- Increased the max explore users from 50 to 100
+- Increased the max feed posts from 40 to 50.
+- Added loading screens.
+- Added updates from Derek Jamison
+
 ## 0.6
 - Improved memory allocation
 - Fixed bugs in Direct Messaging View

+ 13 - 11
assets/README.md

@@ -46,21 +46,22 @@ FlipSocial uses the FlipperHTTP flash for the WiFi Devboard, first introduced in
 - Direct Messaging
 
 **v0.5**
-- Improved memory allocation
-- Improved Feed Page
+- Improve memory allocation
+- Improve Feed Page
 - Raspberry Pi Pico W Support
 
 **v0.6**
-- Improved memory allocation
-- Fixed bugs in Direct Messaging View
-- Fixed bugs in Pre-Save View
+- Improve memory allocation
+- Update the Direct Messaging View
+- Update the Pre-Save View
 
 **v0.7**
-- Improved User Profile (Bio, friend count, block)
-- Improved Explore Page
+- Improve memory allocation
+- Loading screens.
 
 **v0.8**
-- Create and Post Pixel Art
+- Improve User Profile (Bio, friend count, block)
+- Improve Explore Page
 
 **v1.0**
 - Official Release
@@ -88,8 +89,9 @@ This is a big project, and I welcome all contributors, especially developers int
 - **Solution 3:** Ensure your WiFi Devboard is plugged in, then restart your Flipper device.
 
 5. Out of memory when starting the app or after visiting the feed and post views back-to-back.
-- **Solution:** Restart your Flipper device.
+- **Solution 1:** Restart your Flipper device.
+- **Solution 2:** Update the app to version 0.7 (or higher).
 
-6. I can no longer access my Direct Messages.
+6. I can no longer access the Messages.
 - **Solution 1:** Uppdate the app to version 0.6.3 (or higher)
-- **Solution 2:** Click the logout button then login again.
+- **Solution 2:** Click the logout button then login again. Make sure your password is correct before clicking "Login".

Разница между файлами не показана из-за своего большого размера
+ 882 - 45
callback/flip_social_callback.c


+ 48 - 1
callback/flip_social_callback.h

@@ -6,9 +6,10 @@
 #include <friends/flip_social_friends.h>
 #include <explore/flip_social_explore.h>
 #include <feed/flip_social_feed.h>
-#include <draw/flip_social_draw.h>
 #include <flip_storage/flip_social_storage.h>
 
+void flip_social_request_error_draw(Canvas *canvas);
+
 /**
  * @brief Navigation callback to go back to the submenu Logged out.
  * @param context The context - unused
@@ -253,4 +254,50 @@ 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);
+
+bool messages_dialog_alloc(bool free_first);
+bool feed_dialog_alloc();
 #endif

+ 31 - 594
draw/flip_social_draw.c

@@ -15,39 +15,6 @@ bool flip_social_board_is_active(Canvas *canvas)
     return true;
 }
 
-void flip_social_handle_error(Canvas *canvas)
-{
-    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
-        {
-            canvas_draw_str(canvas, 0, 42, "Failed...");
-            canvas_draw_str(canvas, 0, 52, "Update your credentials.");
-            canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
-        }
-    }
-    else
-    {
-        canvas_draw_str(canvas, 0, 42, "Failed...");
-        canvas_draw_str(canvas, 0, 52, "Update your credentials.");
-        canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
-    }
-}
-
 void on_input(const void *event, void *ctx)
 {
     UNUSED(ctx);
@@ -205,7 +172,6 @@ void flip_social_callback_draw_compose(Canvas *canvas, void *model)
             char command[256];
             snprintf(command, sizeof(command), "{\"username\":\"%s\",\"content\":\"%s\"}",
                      app_instance->login_username_logged_in, selected_message);
-
             if (!flipper_http_post_request_with_headers(
                     "https://www.flipsocial.net/api/feed/post/",
                     auth_headers,
@@ -277,18 +243,10 @@ void flip_social_callback_draw_compose(Canvas *canvas, void *model)
             canvas_draw_str(canvas, 0, 50, "Loading feed :D");
             canvas_draw_str(canvas, 0, 60, "Please wait...");
             action = ActionNone;
-            if (flipper_http_process_response_async(flip_social_get_feed, flip_social_parse_json_feed))
+            if (!flip_social_load_initial_feed())
             {
-                view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInFeed);
-            }
-            else
-            {
-                // Set failure FlipSocialFeed object
-                if (!flip_social_temp_feed())
-                {
-                    return;
-                }
-                view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInFeed);
+                FURI_LOG_E(TAG, "Failed to load initial feed");
+                return;
             }
         }
         else if (action == ActionBack)
@@ -422,41 +380,55 @@ void flip_social_callback_draw_feed(Canvas *canvas, void *model)
     switch (action)
     {
     case ActionNone:
-        flip_social_canvas_draw_message(canvas, flip_social_feed->usernames[flip_social_feed->index], flip_social_feed->messages[flip_social_feed->index], flip_social_feed->is_flipped[flip_social_feed->index], flip_social_feed->index > 0, flip_social_feed->index < flip_social_feed->count - 1, flip_social_feed->flips[flip_social_feed->index]);
+        flip_social_canvas_draw_message(canvas, flip_feed_item->username, flip_feed_item->message, flip_feed_item->is_flipped, flip_feed_info->index > 0, flip_feed_info->index < flip_feed_info->count - 1, flip_feed_item->flips);
         break;
     case ActionNext:
         canvas_clear(canvas);
-        if (flip_social_feed->index < flip_social_feed->count - 1)
+        if (flip_feed_info->index < flip_feed_info->count - 1)
         {
-            flip_social_feed->index++;
+            flip_feed_info->index++;
         }
-        flip_social_canvas_draw_message(canvas, flip_social_feed->usernames[flip_social_feed->index], flip_social_feed->messages[flip_social_feed->index], flip_social_feed->is_flipped[flip_social_feed->index], flip_social_feed->index > 0, flip_social_feed->index < flip_social_feed->count - 1, flip_social_feed->flips[flip_social_feed->index]);
+        // load the next feed item
+        if (!flip_social_load_feed_post(flip_feed_info->ids[flip_feed_info->index]))
+        {
+            FURI_LOG_E(TAG, "Failed to load nexy feed post");
+            fhttp.state = ISSUE;
+            return;
+        }
+        flip_social_canvas_draw_message(canvas, flip_feed_item->username, flip_feed_item->message, flip_feed_item->is_flipped, flip_feed_info->index > 0, flip_feed_info->index < flip_feed_info->count - 1, flip_feed_item->flips);
         action = ActionNone;
         break;
     case ActionPrev:
         canvas_clear(canvas);
-        if (flip_social_feed->index > 0)
+        if (flip_feed_info->index > 0)
+        {
+            flip_feed_info->index--;
+        }
+        // load the previous feed item
+        if (!flip_social_load_feed_post(flip_feed_info->ids[flip_feed_info->index]))
         {
-            flip_social_feed->index--;
+            FURI_LOG_E(TAG, "Failed to load nexy feed post");
+            fhttp.state = ISSUE;
+            return;
         }
-        flip_social_canvas_draw_message(canvas, flip_social_feed->usernames[flip_social_feed->index], flip_social_feed->messages[flip_social_feed->index], flip_social_feed->is_flipped[flip_social_feed->index], flip_social_feed->index > 0, flip_social_feed->index < flip_social_feed->count - 1, flip_social_feed->flips[flip_social_feed->index]);
+        flip_social_canvas_draw_message(canvas, flip_feed_item->username, flip_feed_item->message, flip_feed_item->is_flipped, flip_feed_info->index > 0, flip_feed_info->index < flip_feed_info->count - 1, flip_feed_item->flips);
         action = ActionNone;
         break;
     case ActionFlip:
         canvas_clear(canvas);
         // Moved to above the is_flipped check
-        if (!flip_social_feed->is_flipped[flip_social_feed->index])
+        if (!flip_feed_item->is_flipped)
         {
             // increase the flip count
-            flip_social_feed->flips[flip_social_feed->index]++;
+            flip_feed_item->flips++;
         }
         else
         {
             // decrease the flip count
-            flip_social_feed->flips[flip_social_feed->index]--;
+            flip_feed_item->flips--;
         }
         // change the flip status
-        flip_social_feed->is_flipped[flip_social_feed->index] = !flip_social_feed->is_flipped[flip_social_feed->index];
+        flip_feed_item->is_flipped = !flip_feed_item->is_flipped;
         // send post request to flip the message
         if (app_instance->login_username_logged_in == NULL)
         {
@@ -464,15 +436,15 @@ void flip_social_callback_draw_feed(Canvas *canvas, void *model)
             return;
         }
         char payload[256];
-        snprintf(payload, sizeof(payload), "{\"username\":\"%s\",\"post_id\":\"%u\"}", app_instance->login_username_logged_in, flip_social_feed->ids[flip_social_feed->index]);
+        snprintf(payload, sizeof(payload), "{\"username\":\"%s\",\"post_id\":\"%u\"}", app_instance->login_username_logged_in, flip_feed_item->id);
         flipper_http_post_request_with_headers("https://www.flipsocial.net/api/feed/flip/", auth_headers, payload);
-        flip_social_canvas_draw_message(canvas, flip_social_feed->usernames[flip_social_feed->index], flip_social_feed->messages[flip_social_feed->index], flip_social_feed->is_flipped[flip_social_feed->index], flip_social_feed->index > 0, flip_social_feed->index < flip_social_feed->count - 1, flip_social_feed->flips[flip_social_feed->index]);
+        flip_social_canvas_draw_message(canvas, flip_feed_item->username, flip_feed_item->message, flip_feed_item->is_flipped, flip_feed_info->index > 0, flip_feed_info->index < flip_feed_info->count - 1, flip_feed_item->flips);
         action = ActionNone;
         break;
     case ActionBack:
         canvas_clear(canvas);
         flip_social_dialog_stop = true;
-        flip_social_feed->index = 0;
+        flip_feed_info->index = 0;
         action = ActionNone;
         break;
     default:
@@ -486,539 +458,4 @@ void flip_social_callback_draw_feed(Canvas *canvas, void *model)
         flip_social_dialog_stop = false;
         action = ActionNone;
     }
-}
-/**
- * @brief Navigation callback for asynchonously handling the login process.
- * @param canvas The canvas to draw on.
- * @param model The model - unused
- * @return void
- */
-void flip_social_callback_draw_login(Canvas *canvas, void *model)
-{
-    UNUSED(model);
-    if (!canvas)
-    {
-        FURI_LOG_E(TAG, "Canvas is NULL");
-        return;
-    }
-
-    canvas_set_font(canvas, FontSecondary);
-
-    if (!flip_social_board_is_active(canvas))
-    {
-        return;
-    }
-
-    canvas_draw_str(canvas, 0, 7, "Logging in...");
-
-    // Perform login request
-    if (!flip_social_sent_login_request)
-    {
-
-        if (!app_instance->login_username_logged_out || !app_instance->login_password_logged_out || strlen(app_instance->login_username_logged_out) == 0 || strlen(app_instance->login_password_logged_out) == 0)
-        {
-            canvas_clear(canvas);
-            canvas_draw_str(canvas, 0, 10, "Please enter your credentials.");
-            canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
-            return;
-        }
-
-        flip_social_sent_login_request = true;
-
-        char buffer[256];
-        snprintf(buffer, sizeof(buffer), "{\"username\":\"%s\",\"password\":\"%s\"}", app_instance->login_username_logged_out, app_instance->login_password_logged_out);
-        auth_headers_alloc();
-        flip_social_login_success = flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/login/", auth_headers, buffer);
-        if (flip_social_login_success)
-        {
-            fhttp.state = RECEIVING;
-            return;
-        }
-        else
-        {
-            fhttp.state = ISSUE;
-            return;
-        }
-    }
-    // handle response
-    if (flip_social_sent_login_request && flip_social_login_success)
-    {
-        canvas_set_font(canvas, FontSecondary);
-        canvas_draw_str(canvas, 0, 17, "Request Sent!");
-        canvas_draw_str(canvas, 0, 32, "Awaiting reponse...");
-
-        if (fhttp.state == IDLE && fhttp.last_response != NULL)
-        {
-            // read response
-            if (strstr(fhttp.last_response, "[SUCCESS]") != NULL || strstr(fhttp.last_response, "User found") != NULL)
-            {
-                canvas_draw_str(canvas, 0, 42, "Login successful!");
-                canvas_draw_str(canvas, 0, 62, "Welcome back!");
-
-                app_instance->is_logged_in = "true";
-
-                // set the logged_in_username and change_password_logged_in
-                if (app_instance->login_username_logged_out)
-                {
-                    strcpy(app_instance->login_username_logged_in, app_instance->login_username_logged_out);
-                }
-                if (app_instance->login_password_logged_out)
-                {
-                    app_instance->change_password_logged_in = app_instance->login_password_logged_out;
-                }
-
-                save_settings(app_instance->wifi_ssid_logged_out, app_instance->wifi_password_logged_out, app_instance->login_username_logged_out, app_instance->login_username_logged_in, app_instance->login_password_logged_out, app_instance->change_password_logged_in, app_instance->is_logged_in);
-
-                // send user to the logged in submenu
-                view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
-            }
-            else if (strstr(fhttp.last_response, "User not found") != NULL)
-            {
-                canvas_clear(canvas);
-                canvas_draw_str(canvas, 0, 10, "Account not found...");
-                canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
-            }
-            else
-            {
-                flip_social_handle_error(canvas);
-            }
-        }
-        else if ((fhttp.state == ISSUE || fhttp.state == INACTIVE) && fhttp.last_response != NULL)
-        {
-            flip_social_handle_error(canvas);
-        }
-        else if (fhttp.state == IDLE && fhttp.last_response == NULL)
-        {
-            flip_social_handle_error(canvas);
-        }
-    }
-    else if (flip_social_sent_login_request && !flip_social_login_success)
-    {
-        canvas_clear(canvas);
-        canvas_draw_str(canvas, 0, 10, "Failed sending request.");
-        canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
-        canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
-    }
-}
-
-/**
- * @brief Navigation callback for asynchonously handling the register process.
- * @param canvas The canvas to draw on.
- * @param model The model - unused
- * @return void
- */
-void flip_social_callback_draw_register(Canvas *canvas, void *model)
-{
-    UNUSED(model);
-    if (!canvas)
-    {
-        FURI_LOG_E(TAG, "Canvas is NULL");
-        return;
-    }
-
-    canvas_set_font(canvas, FontSecondary);
-
-    if (!flip_social_board_is_active(canvas))
-    {
-        return;
-    }
-
-    canvas_draw_str(canvas, 0, 7, "Registering...");
-
-    // Perform login request
-    if (!flip_social_sent_register_request)
-    {
-        // check if the username and password are valid
-        if (!app_instance->register_username_logged_out || !app_instance->register_password_logged_out || strlen(app_instance->register_username_logged_out) == 0 || strlen(app_instance->register_password_logged_out) == 0)
-        {
-            canvas_clear(canvas);
-            canvas_draw_str(canvas, 0, 10, "Please enter your credentials.");
-            canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
-            return;
-        }
-
-        // check if both passwords match
-        if (strcmp(app_instance->register_password_logged_out, app_instance->register_password_2_logged_out) != 0)
-        {
-            canvas_clear(canvas);
-            canvas_draw_str(canvas, 0, 10, "Passwords do not match.");
-            canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
-            return;
-        }
-
-        char buffer[128];
-        snprintf(buffer, sizeof(buffer), "{\"username\":\"%s\",\"password\":\"%s\"}", app_instance->register_username_logged_out, app_instance->register_password_logged_out);
-        flip_social_register_success = flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/register/", "{\"Content-Type\":\"application/json\"}", buffer);
-
-        flip_social_sent_register_request = true;
-        if (flip_social_register_success)
-        {
-            // Set the state to RECEIVING to ensure we continue to see the receiving message
-            fhttp.state = RECEIVING;
-        }
-        else
-        {
-            fhttp.state = ISSUE;
-        }
-    }
-    // handle response
-    if (flip_social_sent_register_request && flip_social_register_success)
-    {
-        canvas_set_font(canvas, FontSecondary);
-        canvas_draw_str(canvas, 0, 17, "Request Sent!");
-        canvas_draw_str(canvas, 0, 32, "Awaiting reponse...");
-
-        if (fhttp.state == IDLE)
-        {
-            // read response
-            if (fhttp.last_response != NULL && (strstr(fhttp.last_response, "[SUCCESS]") != NULL || strstr(fhttp.last_response, "User created") != NULL))
-            {
-                canvas_draw_str(canvas, 0, 42, "Registeration successful!");
-                canvas_draw_str(canvas, 0, 62, "Welcome to FlipSocial!");
-
-                // set the login credentials
-                if (app_instance->login_username_logged_out)
-                {
-                    app_instance->login_username_logged_out = app_instance->register_username_logged_out;
-                }
-                if (app_instance->login_password_logged_out)
-                {
-                    app_instance->login_password_logged_out = app_instance->register_password_logged_out;
-                    app_instance->change_password_logged_in = app_instance->register_password_logged_out;
-                }
-                if (app_instance->login_username_logged_in)
-                {
-                    app_instance->login_username_logged_in = app_instance->register_username_logged_out;
-                }
-
-                app_instance->is_logged_in = "true";
-
-                // update header credentials
-                auth_headers_alloc();
-
-                // save the credentials
-                save_settings(app_instance->wifi_ssid_logged_out, app_instance->wifi_password_logged_out, app_instance->login_username_logged_out, app_instance->login_username_logged_in, app_instance->login_password_logged_out, app_instance->change_password_logged_in, app_instance->is_logged_in);
-
-                // send user to the logged in submenu
-                view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
-            }
-            else if (strstr(fhttp.last_response, "Username or password not provided") != NULL)
-            {
-                canvas_clear(canvas);
-                canvas_draw_str(canvas, 0, 10, "Please enter your credentials.");
-                canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
-            }
-            else if (strstr(fhttp.last_response, "User already exists") != NULL || strstr(fhttp.last_response, "Multiple users found") != NULL)
-            {
-                canvas_draw_str(canvas, 0, 42, "Registration failed...");
-                canvas_draw_str(canvas, 0, 52, "Username already exists.");
-                canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
-            }
-            else
-            {
-                canvas_draw_str(canvas, 0, 42, "Registration failed...");
-                canvas_draw_str(canvas, 0, 52, "Update your credentials.");
-                canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
-            }
-        }
-        else if (fhttp.state == ISSUE || fhttp.state == INACTIVE)
-        {
-            flip_social_handle_error(canvas);
-        }
-    }
-    else if (flip_social_sent_register_request && !flip_social_register_success)
-    {
-        canvas_clear(canvas);
-        canvas_draw_str(canvas, 0, 10, "Failed sending request.");
-        canvas_draw_str(canvas, 0, 50, "Update your WiFi settings.");
-        canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
-    }
-}
-
-// function to draw the dialog canvas
-void flip_social_canvas_draw_explore(Canvas *canvas, char *user_username, char *content)
-{
-    canvas_set_color(canvas, ColorBlack);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, user_username);
-    canvas_set_font(canvas, FontSecondary);
-
-    draw_user_message(canvas, content, 0, 12);
-
-    canvas_set_font(canvas, FontSecondary);
-    canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7);
-    canvas_draw_str_aligned(canvas, 9, 54, AlignLeft, AlignTop, "Remove");
-    canvas_draw_icon(canvas, 98, 53, &I_ButtonRight_4x7);
-    canvas_draw_str_aligned(canvas, 107, 54, AlignLeft, AlignTop, "Add");
-
-    if (strlen(content) > 0)
-    {
-        last_explore_response = content;
-    }
-}
-
-// Callback function to handle the explore dialog
-void flip_social_callback_draw_explore(Canvas *canvas, void *model)
-{
-    UNUSED(model);
-    if (!canvas)
-    {
-        FURI_LOG_E(TAG, "Canvas is NULL");
-        return;
-    }
-    if (!app_instance)
-    {
-        FURI_LOG_E(TAG, "FlipSocialApp is NULL");
-        return;
-    }
-
-    if (!flip_social_dialog_shown)
-    {
-        flip_social_dialog_shown = true;
-        app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
-        app_instance->input_event = furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
-        auth_headers_alloc();
-    }
-    flip_social_canvas_draw_explore(canvas, flip_social_explore->usernames[flip_social_explore->index], last_explore_response);
-
-    // handle action
-    switch (action)
-    {
-    case ActionNext:
-        // add friend
-        char add_payload[128];
-        snprintf(add_payload, sizeof(add_payload), "{\"username\":\"%s\",\"friend\":\"%s\"}", app_instance->login_username_logged_in, flip_social_explore->usernames[flip_social_explore->index]);
-        flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/add-friend/", auth_headers, add_payload);
-        canvas_clear(canvas);
-        flip_social_canvas_draw_explore(canvas, flip_social_explore->usernames[flip_social_explore->index], "Added!");
-        action = ActionNone;
-        break;
-    case ActionPrev:
-        // remove friend
-        char remove_payload[128];
-        snprintf(remove_payload, sizeof(remove_payload), "{\"username\":\"%s\",\"friend\":\"%s\"}", app_instance->login_username_logged_in, flip_social_explore->usernames[flip_social_explore->index]);
-        flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/remove-friend/", auth_headers, remove_payload);
-        canvas_clear(canvas);
-        flip_social_canvas_draw_explore(canvas, flip_social_explore->usernames[flip_social_explore->index], "Removed!");
-        action = ActionNone;
-        break;
-    case ActionBack:
-        canvas_clear(canvas);
-        flip_social_dialog_stop = true;
-        last_explore_response = "";
-        flip_social_dialog_shown = false;
-        flip_social_explore->index = 0;
-        action = ActionNone;
-        break;
-    default:
-        break;
-    }
-
-    if (flip_social_dialog_stop)
-    {
-        furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
-        flip_social_dialog_shown = false;
-        flip_social_dialog_stop = false;
-        action = ActionNone;
-    }
-}
-
-// Callback function to handle the friends dialog
-void flip_social_callback_draw_friends(Canvas *canvas, void *model)
-{
-    UNUSED(model);
-    if (!canvas)
-    {
-        FURI_LOG_E(TAG, "Canvas is NULL");
-        return;
-    }
-    if (!app_instance)
-    {
-        FURI_LOG_E(TAG, "FlipSocialApp is NULL");
-        return;
-    }
-
-    if (!flip_social_dialog_shown)
-    {
-        flip_social_dialog_shown = true;
-        app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
-        app_instance->input_event = furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
-        auth_headers_alloc();
-    }
-    flip_social_canvas_draw_explore(canvas, flip_social_friends->usernames[flip_social_friends->index], last_explore_response);
-
-    // handle action
-    switch (action)
-    {
-    case ActionNext:
-        // add friend
-        char add_payload[128];
-        snprintf(add_payload, sizeof(add_payload), "{\"username\":\"%s\",\"friend\":\"%s\"}", app_instance->login_username_logged_in, flip_social_friends->usernames[flip_social_friends->index]);
-        if (flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/add-friend/", auth_headers, add_payload))
-        {
-            canvas_clear(canvas);
-            flip_social_canvas_draw_explore(canvas, flip_social_friends->usernames[flip_social_friends->index], "Added!");
-
-            // add the friend to the friends list
-            flip_social_friends->usernames[flip_social_friends->count] = flip_social_friends->usernames[flip_social_friends->index];
-            flip_social_friends->count++;
-            if (!flip_social_update_friends())
-            {
-                FURI_LOG_E(TAG, "Failed to update friends");
-            }
-        }
-        action = ActionNone;
-        break;
-    case ActionPrev:
-        // remove friend
-        char remove_payload[128];
-        snprintf(remove_payload, sizeof(remove_payload), "{\"username\":\"%s\",\"friend\":\"%s\"}", app_instance->login_username_logged_in, flip_social_friends->usernames[flip_social_friends->index]);
-        if (flipper_http_post_request_with_headers("https://www.flipsocial.net/api/user/remove-friend/", auth_headers, remove_payload))
-        {
-            canvas_clear(canvas);
-            flip_social_canvas_draw_explore(canvas, flip_social_friends->usernames[flip_social_friends->index], "Removed!");
-
-            // remove the friend from the friends list
-            for (int i = flip_social_friends->index; i < flip_social_friends->count - 1; i++)
-            {
-                flip_social_friends->usernames[i] = flip_social_friends->usernames[i + 1];
-            }
-            flip_social_friends->count--;
-            if (!flip_social_update_friends())
-            {
-                FURI_LOG_E(TAG, "Failed to update friends");
-            }
-        }
-        action = ActionNone;
-        break;
-    case ActionBack:
-        canvas_clear(canvas);
-        flip_social_dialog_stop = true;
-        last_explore_response = "";
-        flip_social_dialog_shown = false;
-        flip_social_friends->index = 0;
-        action = ActionNone;
-        break;
-    default:
-        break;
-    }
-
-    if (flip_social_dialog_stop)
-    {
-        furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
-        flip_social_dialog_shown = false;
-        flip_social_dialog_stop = false;
-        action = ActionNone;
-    }
-}
-
-void flip_social_canvas_draw_user_message(Canvas *canvas, char *user_username, char *user_message, bool show_prev, bool show_next)
-{
-    canvas_set_color(canvas, ColorBlack);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, user_username);
-    canvas_set_font(canvas, FontSecondary);
-
-    draw_user_message(canvas, user_message, 0, 12);
-
-    canvas_set_font(canvas, FontSecondary);
-    if (show_prev)
-    {
-        canvas_draw_icon(canvas, 0, 53, &I_ButtonLeft_4x7);
-        canvas_draw_str_aligned(canvas, 9, 54, AlignLeft, AlignTop, "Prev");
-    }
-
-    canvas_draw_icon(canvas, 47, 53, &I_ButtonOK_7x7);
-    canvas_draw_str_aligned(canvas, 56, 54, AlignLeft, AlignTop, "Create");
-
-    if (show_next)
-    {
-        canvas_draw_icon(canvas, 98, 53, &I_ButtonRight_4x7);
-        canvas_draw_str_aligned(canvas, 107, 54, AlignLeft, AlignTop, "Next");
-    }
-}
-
-// Callback function to handle the messages dialog
-void flip_social_callback_draw_messages(Canvas *canvas, void *model)
-{
-    UNUSED(model);
-    if (!canvas)
-    {
-        FURI_LOG_E(TAG, "Canvas is NULL");
-        return;
-    }
-    if (!app_instance)
-    {
-        FURI_LOG_E(TAG, "FlipSocialApp is NULL");
-        return;
-    }
-
-    if (!flip_social_dialog_shown)
-    {
-        flip_social_dialog_shown = true;
-        app_instance->input_event_queue = furi_record_open(RECORD_INPUT_EVENTS);
-        app_instance->input_event = furi_pubsub_subscribe(app_instance->input_event_queue, on_input, NULL);
-    }
-
-    // handle action
-    switch (action)
-    {
-    case ActionNone:
-        flip_social_canvas_draw_user_message(canvas, flip_social_messages->usernames[flip_social_messages->index], flip_social_messages->messages[flip_social_messages->index], flip_social_messages->index > 0, flip_social_messages->index < flip_social_messages->count - 1);
-        action = ActionNone;
-        break;
-    case ActionNext:
-        // view next message (if any)
-        canvas_clear(canvas);
-        if (flip_social_messages->index < flip_social_messages->count - 1)
-        {
-            flip_social_messages->index++;
-        }
-        flip_social_canvas_draw_user_message(canvas, flip_social_messages->usernames[flip_social_messages->index], flip_social_messages->messages[flip_social_messages->index], flip_social_messages->index > 0, flip_social_messages->index < flip_social_messages->count - 1);
-        action = ActionNone;
-        break;
-    case ActionPrev:
-        // view previous message (if any)
-        canvas_clear(canvas);
-        if (flip_social_messages->index > 0)
-        {
-            flip_social_messages->index--;
-        }
-        flip_social_canvas_draw_user_message(canvas, flip_social_messages->usernames[flip_social_messages->index], flip_social_messages->messages[flip_social_messages->index], flip_social_messages->index > 0, flip_social_messages->index < flip_social_messages->count - 1);
-        action = ActionNone;
-        break;
-    case ActionBack:
-        //  go back to the previous view
-        flip_social_dialog_stop = true;
-        action = ActionNone;
-        break;
-    case ActionFlip:
-        // go to the input view
-        flip_social_dialog_stop = true;
-        flip_social_send_message = true;
-        action = ActionNone;
-        break;
-    default:
-        action = ActionNone;
-        break;
-    }
-
-    if (flip_social_dialog_stop && flip_social_dialog_shown)
-    {
-        furi_pubsub_unsubscribe(app_instance->input_event_queue, app_instance->input_event);
-        flip_social_dialog_shown = false;
-        flip_social_dialog_stop = false;
-        if (flip_social_send_message)
-        {
-            FURI_LOG_I(TAG, "Switching to new message input view");
-            action = ActionNone;
-            flip_social_send_message = false;
-            view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInMessagesNewMessageInput);
-        }
-        else
-        {
-            action = ActionNone;
-            view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInMessagesSubmenu);
-        }
-    }
 }

+ 0 - 27
draw/flip_social_draw.h

@@ -29,32 +29,5 @@ void flip_social_callback_draw_compose(Canvas *canvas, void *model);
 void flip_social_canvas_draw_message(Canvas *canvas, char *user_username, char *user_message, bool is_flipped, bool show_prev, bool show_next, int flip_count);
 // Callback function to handle the feed dialog
 void flip_social_callback_draw_feed(Canvas *canvas, void *model);
-/**
- * @brief Navigation callback for asynchonously handling the login process.
- * @param canvas The canvas to draw on.
- * @param model The model - unused
- * @return void
- */
-void flip_social_callback_draw_login(Canvas *canvas, void *model);
-/**
- * @brief Navigation callback for asynchonously handling the register process.
- * @param canvas The canvas to draw on.
- * @param model The model - unused
- * @return void
- */
-void flip_social_callback_draw_register(Canvas *canvas, void *model);
-
-// function to draw the dialog canvas
-void flip_social_canvas_draw_explore(Canvas *canvas, char *user_username, char *content);
-
-// Callback function to handle the explore dialog
-void flip_social_callback_draw_explore(Canvas *canvas, void *model);
-
-// Callback function to handle the friends dialog
-void flip_social_callback_draw_friends(Canvas *canvas, void *model);
-
-void flip_social_canvas_draw_user_message(Canvas *canvas, char *user_username, char *user_message, bool show_prev, bool show_next);
-// Callback function to handle the messages dialog
-void flip_social_callback_draw_messages(Canvas *canvas, void *model);
 
 #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>

+ 46 - 69
explore/flip_social_explore.c

@@ -1,7 +1,20 @@
 #include "flip_social_explore.h"
 
-FlipSocialModel *flip_social_explore_alloc()
+FlipSocialModel *flip_social_explore_alloc(void)
 {
+    if (!app_instance)
+    {
+        return NULL;
+    }
+
+    if (!app_instance->submenu_explore)
+    {
+        if (!easy_flipper_set_submenu(&app_instance->submenu_explore, FlipSocialViewLoggedInExploreSubmenu, "Explore", flip_social_callback_to_submenu_logged_in, &app_instance->view_dispatcher))
+        {
+            return NULL;
+        }
+    }
+
     // Allocate memory for each username only if not already allocated
     FlipSocialModel *explore = malloc(sizeof(FlipSocialModel));
     if (explore == NULL)
@@ -24,30 +37,39 @@ FlipSocialModel *flip_social_explore_alloc()
     return explore;
 }
 
-void flip_social_free_explore()
+void flip_social_free_explore(void)
 {
-    if (!flip_social_explore)
+    if (!app_instance)
     {
-        FURI_LOG_E(TAG, "Explore model is NULL");
         return;
     }
-    for (int i = 0; i < flip_social_explore->count; i++)
+    if (app_instance->submenu_explore)
     {
-        if (flip_social_explore->usernames[i])
-        {
-            free(flip_social_explore->usernames[i]);
-        }
+        submenu_free(app_instance->submenu_explore);
+        app_instance->submenu_explore = NULL;
+        view_dispatcher_remove_view(app_instance->view_dispatcher, FlipSocialViewLoggedInExploreSubmenu);
     }
+    if (!flip_social_explore)
+    {
+        return;
+    }
+    free(flip_social_explore);
+    flip_social_explore = NULL;
 }
 
 // for now we're just listing the current users
 // as the feed is upgraded, then we can port more to the explore view
-bool flip_social_get_explore()
+bool flip_social_get_explore(void)
 {
+    if (fhttp.state == INACTIVE)
+    {
+        FURI_LOG_E(TAG, "HTTP state is INACTIVE");
+        return false;
+    }
     snprintf(
         fhttp.file_path,
         sizeof(fhttp.file_path),
-        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/users.txt");
+        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/users.json");
 
     fhttp.save_received_data = true;
     auth_headers_alloc();
@@ -88,72 +110,27 @@ bool flip_social_parse_json_explore()
         return false;
     }
 
-    // Remove newlines
-    char *pos = data_cstr;
-    while ((pos = strchr(pos, '\n')) != NULL)
-    {
-        *pos = ' ';
-    }
-
     // Initialize explore count
     flip_social_explore->count = 0;
 
-    // Extract the users array from the JSON
-    char *json_users = get_json_value("users", data_cstr, MAX_TOKENS);
-    if (json_users == NULL)
-    {
-        FURI_LOG_E(TAG, "Failed to parse users array.");
-        furi_string_free(user_data);
-        free(data_cstr);
-        return false;
-    }
-
-    // Manual tokenization for comma-separated values
-    char *start = json_users + 1; // Skip the opening bracket
-    char *end;
-    while ((end = strchr(start, ',')) != NULL && flip_social_explore->count < MAX_EXPLORE_USERS)
-    {
-        *end = '\0'; // Null-terminate the current token
-
-        // Remove quotes
-        if (*start == '"')
-            start++;
-        if (*(end - 1) == '"')
-            *(end - 1) = '\0';
-
-        // Copy username to pre-allocated memory
-        snprintf(flip_social_explore->usernames[flip_social_explore->count], MAX_USER_LENGTH, "%s", start);
-        flip_social_explore->count++;
-        start = end + 1;
-    }
-
-    // Handle the last token
-    if (*start != '\0' && flip_social_explore->count < MAX_EXPLORE_USERS)
-    {
-        if (*start == '"')
-            start++;
-        if (*(start + strlen(start) - 1) == ']')
-            *(start + strlen(start) - 1) = '\0';
-        if (*(start + strlen(start) - 1) == '"')
-            *(start + strlen(start) - 1) = '\0';
-
-        snprintf(flip_social_explore->usernames[flip_social_explore->count], MAX_USER_LENGTH, "%s", start);
-        flip_social_explore->count++;
-    }
-
-    // Add submenu items for the users
+    // set submenu
     submenu_reset(app_instance->submenu_explore);
     submenu_set_header(app_instance->submenu_explore, "Explore");
-    for (int i = 0; i < flip_social_explore->count; i++)
+
+    // Parse the JSON array of usernames
+    for (size_t i = 0; i < MAX_EXPLORE_USERS; i++)
     {
+        char *username = get_json_array_value("users", i, data_cstr, MAX_TOKENS); // currently its 330 tokens
+        if (username == NULL)
+        {
+            break;
+        }
+        snprintf(flip_social_explore->usernames[i], MAX_USER_LENGTH, "%s", username);
         submenu_add_item(app_instance->submenu_explore, flip_social_explore->usernames[i], FlipSocialSubmenuExploreIndexStartIndex + i, flip_social_callback_submenu_choices, app_instance);
+        flip_social_explore->count++;
+        free(username);
     }
-
-    // Free the json_users
-    free(json_users);
-    free(start);
-    free(end);
-    furi_string_free(user_data);
     free(data_cstr);
+    furi_string_free(user_data);
     return flip_social_explore->count > 0;
 }

+ 188 - 136
feed/flip_social_feed.c

@@ -1,114 +1,5 @@
 #include "flip_social_feed.h"
 
-// Set failure FlipSocialFeed object
-bool flip_social_temp_feed()
-{
-    if (flip_social_feed == NULL)
-    {
-        flip_social_feed = malloc(sizeof(FlipSocialFeed));
-        if (flip_social_feed == NULL)
-        {
-            FURI_LOG_E(TAG, "Failed to allocate memory for feed");
-            return false;
-        }
-    }
-    for (int i = 0; i < 3; i++)
-    {
-        if (flip_social_feed->usernames[i] == NULL)
-        {
-            flip_social_feed->usernames[i] = malloc(MAX_USER_LENGTH);
-            if (flip_social_feed->usernames[i] == NULL)
-            {
-                FURI_LOG_E(TAG, "Failed to allocate memory for username %zu", i);
-                return false;
-            }
-        }
-        if (flip_social_feed->messages[i] == NULL)
-        {
-            flip_social_feed->messages[i] = malloc(MAX_MESSAGE_LENGTH);
-            if (flip_social_feed->messages[i] == NULL)
-            {
-                FURI_LOG_E(TAG, "Failed to allocate memory for message %zu", i);
-                return false;
-            }
-        }
-    }
-    flip_social_feed->usernames[0] = "JBlanked";
-    flip_social_feed->usernames[1] = "FlipperKing";
-    flip_social_feed->usernames[2] = "FlipperQueen";
-    //
-    flip_social_feed->messages[0] = "Welcome. This is a temp message. Either the feed didn't load or there was a server error.";
-    flip_social_feed->messages[1] = "I am the Chosen Flipper.";
-    flip_social_feed->messages[2] = "No one can flip like me.";
-    //
-    flip_social_feed->is_flipped[0] = true;
-    flip_social_feed->is_flipped[1] = false;
-    flip_social_feed->is_flipped[2] = true;
-    //
-    flip_social_feed->ids[0] = 0;
-    flip_social_feed->ids[1] = 1;
-    flip_social_feed->ids[2] = 2;
-    //
-    flip_social_feed->flips[0] = 51;
-    flip_social_feed->flips[1] = 8;
-    flip_social_feed->flips[2] = 23;
-    //
-    flip_social_feed->count = 3;
-    flip_social_feed->index = 0;
-
-    return true;
-}
-
-// Allocate memory for each feed item if not already allocated
-FlipSocialFeed *flip_social_feed_alloc()
-{
-    // Initialize the feed
-    FlipSocialFeed *feed = (FlipSocialFeed *)malloc(sizeof(FlipSocialFeed));
-    if (!feed)
-    {
-        FURI_LOG_E(TAG, "Failed to allocate memory for feed");
-        return feed;
-    }
-    for (size_t i = 0; i < MAX_FEED_ITEMS; i++)
-    {
-        if (feed->usernames[i] == NULL)
-        {
-            feed->usernames[i] = malloc(MAX_USER_LENGTH);
-            if (feed->usernames[i] == NULL)
-            {
-                FURI_LOG_E(TAG, "Failed to allocate memory for username %zu", i);
-                return NULL;
-            }
-        }
-        if (feed->messages[i] == NULL)
-        {
-            feed->messages[i] = malloc(MAX_MESSAGE_LENGTH);
-            if (feed->messages[i] == NULL)
-            {
-                FURI_LOG_E(TAG, "Failed to allocate memory for message %zu", i);
-                return NULL;
-            }
-        }
-    }
-    return feed;
-}
-
-void flip_social_free_feed()
-{
-    if (!flip_social_feed)
-    {
-        FURI_LOG_E(TAG, "Feed model is NULL");
-        return;
-    }
-    for (uint32_t i = 0; i < flip_social_feed->count; i++)
-    {
-        if (flip_social_feed->usernames[i])
-        {
-            free(flip_social_feed->usernames[i]);
-        }
-    }
-}
-
 bool flip_social_get_feed()
 {
     if (!app_instance)
@@ -116,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)
     {
@@ -125,12 +21,12 @@ bool flip_social_get_feed()
     snprintf(
         fhttp.file_path,
         sizeof(fhttp.file_path),
-        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/feed.txt");
+        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/feed.json");
 
     fhttp.save_received_data = true;
     auth_headers_alloc();
     char command[96];
-    snprintf(command, 96, "https://www.flipsocial.net/api/feed/40/%s/extended/", app_instance->login_username_logged_out);
+    snprintf(command, 96, "https://www.flipsocial.net/api/feed/50/%s/extended/", app_instance->login_username_logged_out);
     if (!flipper_http_get_request_with_headers(command, auth_headers))
     {
         FURI_LOG_E(TAG, "Failed to send HTTP request for feed");
@@ -141,29 +37,30 @@ bool flip_social_get_feed()
     return true;
 }
 
-bool flip_social_parse_json_feed()
+FlipSocialFeedMini *flip_social_parse_json_feed()
 {
     // load the received data from the saved file
     FuriString *feed_data = flipper_http_load_from_file(fhttp.file_path);
     if (feed_data == NULL)
     {
         FURI_LOG_E(TAG, "Failed to load received data from file.");
-        return false;
+        return NULL;
     }
     char *data_cstr = (char *)furi_string_get_cstr(feed_data);
     if (data_cstr == NULL)
     {
         FURI_LOG_E(TAG, "Failed to get C-string from FuriString.");
         furi_string_free(feed_data);
-        return false;
+        return NULL;
     }
 
-    // Allocate memory for each feed item if not already allocated
-    flip_social_feed = flip_social_feed_alloc();
-    if (flip_social_feed == NULL)
+    FlipSocialFeedMini *feed_info = (FlipSocialFeedMini *)malloc(sizeof(FlipSocialFeedMini));
+    if (!feed_info)
     {
-        return false;
+        FURI_LOG_E(TAG, "Failed to allocate memory for feed_info");
+        return NULL;
     }
+
     // Remove newlines
     char *pos = data_cstr;
     while ((pos = strchr(pos, '\n')) != NULL)
@@ -171,8 +68,7 @@ bool flip_social_parse_json_feed()
         *pos = ' ';
     }
 
-    // Initialize feed count
-    flip_social_feed->count = 0;
+    int feed_count = 0;
 
     // Iterate through the feed array
     for (int i = 0; i < MAX_FEED_ITEMS; i++)
@@ -185,11 +81,11 @@ bool flip_social_parse_json_feed()
         }
 
         // Extract individual fields from the JSON object
-        char *username = get_json_value("username", item, MAX_TOKENS);
-        char *message = get_json_value("message", item, MAX_TOKENS);
-        char *flipped = get_json_value("flipped", item, MAX_TOKENS);
-        char *flips = get_json_value("flip_count", item, MAX_TOKENS);
-        char *id = get_json_value("id", item, MAX_TOKENS);
+        char *username = get_json_value("username", item, 40);
+        char *message = get_json_value("message", item, 40);
+        char *flipped = get_json_value("flipped", item, 40);
+        char *flips = get_json_value("flip_count", item, 40);
+        char *id = get_json_value("id", item, 40);
 
         if (username == NULL || message == NULL || flipped == NULL || id == NULL)
         {
@@ -203,16 +99,19 @@ bool flip_social_parse_json_feed()
             continue;
         }
 
-        // Safely copy strings with bounds checking
-        snprintf(flip_social_feed->usernames[i], MAX_USER_LENGTH, "%s", username);
-        snprintf(flip_social_feed->messages[i], MAX_MESSAGE_LENGTH, "%s", message);
-
-        // Store boolean and integer values
-        flip_social_feed->is_flipped[i] = strstr(flipped, "true") != NULL;
-        flip_social_feed->ids[i] = atoi(id);
-        flip_social_feed->flips[i] = atoi(flips);
-
-        flip_social_feed->count++;
+        if (!flip_social_save_post(id, item))
+        {
+            FURI_LOG_E(TAG, "Failed to save post.");
+            free(item);
+            free(username);
+            free(message);
+            free(flipped);
+            free(flips);
+            free(id);
+            continue;
+        }
+        feed_count++;
+        feed_info->ids[i] = atoi(id);
 
         // Free allocated memory
         free(item);
@@ -223,7 +122,160 @@ bool flip_social_parse_json_feed()
         free(id);
     }
 
+    // Store the number of feed items
+    feed_info->count = feed_count;
+    feed_info->index = 0;
+
     furi_string_free(feed_data);
     free(data_cstr);
-    return flip_social_feed->count > 0;
+    return feed_info;
 }
+
+bool flip_social_load_feed_post(int post_id)
+{
+    char file_path[128];
+    snprintf(file_path, sizeof(file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/feed_post_%d.json", post_id);
+
+    // load the received data from the saved file
+    FuriString *feed_data = flipper_http_load_from_file(file_path);
+    if (feed_data == NULL)
+    {
+        FURI_LOG_E(TAG, "Failed to load received data from file.");
+        return false;
+    }
+    char *data_cstr = (char *)furi_string_get_cstr(feed_data);
+    if (data_cstr == NULL)
+    {
+        FURI_LOG_E(TAG, "Failed to get C-string from FuriString.");
+        furi_string_free(feed_data);
+        return false;
+    }
+
+    // Parse the feed post
+    if (!flip_feed_item)
+    {
+        flip_feed_item = (FlipSocialFeedItem *)malloc(sizeof(FlipSocialFeedItem));
+        if (flip_feed_item == NULL)
+        {
+            FURI_LOG_E(TAG, "Failed to allocate memory for feed post.");
+            furi_string_free(feed_data);
+            free(data_cstr);
+            return false;
+        }
+        flip_feed_item->username = malloc(MAX_USER_LENGTH);
+        flip_feed_item->message = malloc(MAX_MESSAGE_LENGTH);
+    }
+
+    // Extract individual fields from the JSON object
+    char *username = get_json_value("username", data_cstr, 40);
+    char *message = get_json_value("message", data_cstr, 40);
+    char *flipped = get_json_value("flipped", data_cstr, 40);
+    char *flips = get_json_value("flip_count", data_cstr, 40);
+    char *id = get_json_value("id", data_cstr, 40);
+
+    if (username == NULL || message == NULL || flipped == NULL || id == NULL)
+    {
+        FURI_LOG_E(TAG, "Failed to parse item fields.");
+        free(username);
+        free(message);
+        free(flipped);
+        free(flips);
+        free(id);
+        free(data_cstr);
+        furi_string_free(feed_data);
+        return false;
+    }
+
+    // Safely copy strings with bounds checking
+    snprintf(flip_feed_item->username, MAX_USER_LENGTH, "%s", username);
+    snprintf(flip_feed_item->message, MAX_MESSAGE_LENGTH, "%s", message);
+
+    // Store boolean and integer values
+    flip_feed_item->is_flipped = strstr(flipped, "true") != NULL;
+    flip_feed_item->id = atoi(id);
+    flip_feed_item->flips = atoi(flips);
+
+    // Free allocated memory
+    free(username);
+    free(message);
+    free(flipped);
+    free(flips);
+    free(id);
+
+    furi_string_free(feed_data);
+    free(data_cstr);
+
+    return true;
+}
+
+bool flip_social_load_initial_feed()
+{
+    if (fhttp.state == INACTIVE)
+    {
+        FURI_LOG_E(TAG, "HTTP state is INACTIVE");
+        return false;
+    }
+    if (!easy_flipper_set_loading(&app_instance->loading, FlipSocialViewLoading, flip_social_callback_to_submenu_logged_in, &app_instance->view_dispatcher))
+    {
+        FURI_LOG_E(TAG, "Failed to set loading screen");
+        return false;
+    }
+    view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoading);
+    if (flip_social_get_feed()) // start the async request
+    {
+        furi_timer_start(fhttp.get_timeout_timer, TIMEOUT_DURATION_TICKS);
+        fhttp.state = RECEIVING;
+    }
+    else
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to send request");
+        fhttp.state = ISSUE;
+        view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
+        view_dispatcher_remove_view(app_instance->view_dispatcher, FlipSocialViewLoading);
+        loading_free(app_instance->loading);
+        return false;
+    }
+    while (fhttp.state == RECEIVING && furi_timer_is_running(fhttp.get_timeout_timer) > 0)
+    {
+        // Wait for the request to be received
+        furi_delay_ms(100);
+    }
+    furi_timer_stop(fhttp.get_timeout_timer);
+
+    // load feed info
+    flip_feed_info = flip_social_parse_json_feed();
+    if (!flip_feed_info || flip_feed_info->count < 1)
+    {
+        FURI_LOG_E(TAG, "Failed to parse JSON feed");
+        fhttp.state = ISSUE;
+        view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
+        view_dispatcher_remove_view(app_instance->view_dispatcher, FlipSocialViewLoading);
+        loading_free(app_instance->loading);
+        return false;
+    }
+
+    // load the current feed post
+    if (!flip_social_load_feed_post(flip_feed_info->ids[flip_feed_info->index]))
+    {
+        FURI_LOG_E(TAG, "Failed to load feed post");
+        fhttp.state = ISSUE;
+        view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
+        view_dispatcher_remove_view(app_instance->view_dispatcher, FlipSocialViewLoading);
+        loading_free(app_instance->loading);
+        return false;
+    }
+    if (!feed_dialog_alloc())
+    {
+        FURI_LOG_E(TAG, "Failed to allocate feed dialog");
+        fhttp.state = ISSUE;
+        view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewLoggedInSubmenu);
+        view_dispatcher_remove_view(app_instance->view_dispatcher, FlipSocialViewLoading);
+        loading_free(app_instance->loading);
+        return false;
+    }
+    view_dispatcher_switch_to_view(app_instance->view_dispatcher, FlipSocialViewFeedDialog);
+    view_dispatcher_remove_view(app_instance->view_dispatcher, FlipSocialViewLoading);
+    loading_free(app_instance->loading);
+
+    return true;
+}

+ 5 - 5
feed/flip_social_feed.h

@@ -2,10 +2,10 @@
 #define FLIP_SOCIAL_FEED_H
 #include "flip_social.h"
 #include <callback/flip_social_callback.h>
+#include <flip_storage/flip_social_storage.h>
 
-bool flip_social_temp_feed();
-FlipSocialFeed *flip_social_feed_alloc();
-void flip_social_free_feed();
 bool flip_social_get_feed();
-bool flip_social_parse_json_feed();
-#endif
+bool flip_social_load_feed_post(int post_id);
+bool flip_social_load_initial_feed();
+FlipSocialFeedMini *flip_social_parse_json_feed();
+#endif

+ 39 - 66
flip_social.c

@@ -1,11 +1,11 @@
 #include "flip_social.h"
 
-FlipSocialFeed *flip_social_feed = NULL;            // Store the feed
 FlipSocialModel *flip_social_friends = NULL;        // Store the friends
 FlipSocialModel2 *flip_social_message_users = NULL; // Store the users that have sent messages to the logged in user
 FlipSocialModel *flip_social_explore = NULL;        // Store the users to explore
 FlipSocialMessage *flip_social_messages = NULL;     // Store the messages between the logged in user and the selected user
-
+FlipSocialFeedMini *flip_feed_info = NULL;          // Store the feed info
+FlipSocialFeedItem *flip_feed_item = NULL;          // Store a feed item
 FlipSocialApp *app_instance = NULL;
 
 bool flip_social_sent_login_request = false;
@@ -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.
@@ -50,26 +52,7 @@ void flip_social_app_free(FlipSocialApp *app)
         view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInSubmenu);
         submenu_free(app->submenu_logged_in);
     }
-    if (app->submenu_compose)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInCompose);
-        submenu_free(app->submenu_compose);
-    }
-    if (app->submenu_explore)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInExploreSubmenu);
-        submenu_free(app->submenu_explore);
-    }
-    if (app->submenu_friends)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInFriendsSubmenu);
-        submenu_free(app->submenu_friends);
-    }
-    if (app->submenu_messages)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInMessagesSubmenu);
-        submenu_free(app->submenu_messages);
-    }
+    //
     if (app->submenu_messages_user_choices)
     {
         view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInMessagesUserChoices);
@@ -176,52 +159,18 @@ void flip_social_app_free(FlipSocialApp *app)
     }
 
     // Free Widget(s)
-    if (app->widget_logged_out_about)
+    if (app->widget_result)
     {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedOutAbout);
-        widget_free(app->widget_logged_out_about);
-    }
-    if (app->widget_logged_in_about)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInSettingsAbout);
-        widget_free(app->widget_logged_in_about);
+        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewWidgetResult);
+        widget_free(app->widget_result);
     }
 
     // Free View(s)
-    if (app->view_process_login)
+    if (app->view_loader)
     {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedOutProcessLogin);
-        view_free(app->view_process_login);
-    }
-    if (app->view_process_register)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedOutProcessRegister);
-        view_free(app->view_process_register);
-    }
-    if (app->view_process_feed)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInFeed);
-        view_free(app->view_process_feed);
-    }
-    if (app->view_process_compose)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInProcessCompose);
-        view_free(app->view_process_compose);
-    }
-    if (app->view_process_explore)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInExploreProccess);
-        view_free(app->view_process_explore);
-    }
-    if (app->view_process_friends)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInFriendsProcess);
-        view_free(app->view_process_friends);
-    }
-    if (app->view_process_messages)
-    {
-        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoggedInMessagesProcess);
-        view_free(app->view_process_messages);
+        view_dispatcher_remove_view(app->view_dispatcher, FlipSocialViewLoader);
+        flip_social_loader_free_model(app->view_loader);
+        view_free(app->view_loader);
     }
 
     if (app->view_dispatcher)
@@ -306,14 +255,15 @@ void auth_headers_alloc(void)
 {
     if (!app_instance)
     {
+        snprintf(auth_headers, sizeof(auth_headers), "{\"Content-Type\":\"application/json\"}");
         return;
     }
 
-    if (app_instance->login_username_logged_out && app_instance->login_password_logged_out)
+    if (app_instance->login_username_logged_out && app_instance->login_password_logged_out && strlen(app_instance->login_username_logged_out) > 0 && strlen(app_instance->login_password_logged_out) > 0)
     {
         snprintf(auth_headers, sizeof(auth_headers), "{\"Content-Type\":\"application/json\",\"username\":\"%s\",\"password\":\"%s\"}", app_instance->login_username_logged_out, app_instance->login_password_logged_out);
     }
-    else if (app_instance->login_username_logged_in && app_instance->change_password_logged_in)
+    else if (app_instance->login_username_logged_in && app_instance->change_password_logged_in && strlen(app_instance->login_username_logged_in) > 0 && strlen(app_instance->change_password_logged_in) > 0)
     {
         snprintf(auth_headers, sizeof(auth_headers), "{\"Content-Type\":\"application/json\",\"username\":\"%s\",\"password\":\"%s\"}", app_instance->login_username_logged_in, app_instance->change_password_logged_in);
     }
@@ -321,4 +271,27 @@ void auth_headers_alloc(void)
     {
         snprintf(auth_headers, sizeof(auth_headers), "{\"Content-Type\":\"application/json\"}");
     }
-}
+}
+
+FlipSocialFeedMini *flip_feed_info_alloc(void)
+{
+    FlipSocialFeedMini *feed_info = (FlipSocialFeedMini *)malloc(sizeof(FlipSocialFeedMini));
+    if (!feed_info)
+    {
+        FURI_LOG_E(TAG, "Failed to allocate memory for feed_info");
+        return NULL;
+    }
+    feed_info->count = 0;
+    feed_info->index = 0;
+    return feed_info;
+}
+
+void flip_feed_info_free(void)
+{
+    if (!flip_feed_info)
+    {
+        return;
+    }
+    free(flip_feed_info);
+    flip_feed_info = NULL;
+}

+ 44 - 27
flip_social.h

@@ -9,13 +9,13 @@
 #include <flip_social_icons.h>
 #define TAG "FlipSocial"
 
-#define MAX_PRE_SAVED_MESSAGES 25 // Maximum number of pre-saved messages
+#define MAX_PRE_SAVED_MESSAGES 20 // Maximum number of pre-saved messages
 #define MAX_MESSAGE_LENGTH 100    // Maximum length of a message in the feed
-#define MAX_EXPLORE_USERS 50      // Maximum number of users to explore
+#define MAX_EXPLORE_USERS 100     // Maximum number of users to explore
 #define MAX_USER_LENGTH 32        // Maximum length of a username
 #define MAX_FRIENDS 50            // Maximum number of friends
-#define MAX_TOKENS 450            // Adjust based on expected JSON tokens
-#define MAX_FEED_ITEMS 41         // Maximum number of feed items
+#define MAX_TOKENS 640            // Adjust based on expected JSON tokens
+#define MAX_FEED_ITEMS 50         // Maximum number of feed items
 #define MAX_LINE_LENGTH 30
 #define MAX_MESSAGE_USERS 20 // Maximum number of users to display in the submenu
 #define MAX_MESSAGES 20      // Maximum number of meesages between each user
@@ -44,13 +44,13 @@ typedef enum
     FlipSocialSubmenuComposeIndexAddPreSave,       // click to add a pre-saved message
     FlipSocialSubemnuComposeIndexStartIndex = 100, // starting index for the first pre saved message
     //
-    FlipSocialSubmenuExploreIndexStartIndex = 150, // starting index for the users to explore
+    FlipSocialSubmenuExploreIndexStartIndex = 200, // starting index for the users to explore
     //
-    FlipSocialSubmenuLoggedInIndexFriendsStart = 200, // starting index for the friends
+    FlipSocialSubmenuLoggedInIndexFriendsStart = 400, // starting index for the friends
     //
-    FlipSocialSubmenuLoggedInIndexMessagesUsersStart = 250, // starting index for the messages
+    FlipSocialSubmenuLoggedInIndexMessagesUsersStart = 600, // starting index for the messages
     //
-    FlipSocialSubmenuLoggedInIndexMessagesUserChoicesIndexStart = 300, // click to select a user to message
+    FlipSocialSubmenuLoggedInIndexMessagesUserChoicesIndexStart = 800, // click to select a user to message
 } FlipSocialSubmenuIndex;
 
 // Define the ScriptPlaylist structure
@@ -61,16 +61,22 @@ typedef struct
     size_t index;
 } PreSavedPlaylist;
 
+// Define a FlipSocialFeed individual item
+typedef struct
+{
+    char *username;
+    char *message;
+    bool is_flipped;
+    int id;
+    int flips;
+} FlipSocialFeedItem;
+
 typedef struct
 {
-    char *usernames[MAX_FEED_ITEMS];
-    char *messages[MAX_FEED_ITEMS];
-    bool is_flipped[MAX_FEED_ITEMS];
     int ids[MAX_FEED_ITEMS];
-    int flips[MAX_FEED_ITEMS];
     size_t count;
     size_t index;
-} FlipSocialFeed;
+} FlipSocialFeedMini;
 
 typedef struct
 {
@@ -130,21 +136,31 @@ typedef enum
     FlipSocialViewLoggedInSettingsWifi,              // The wifi settings screen
     FlipSocialViewLoggedInWifiSettingsSSIDInput,     // Text input screen for SSID input on wifi screen
     FlipSocialViewLoggedInWifiSettingsPasswordInput, // Text input screen for Password input on wifi screen
-    FlipSocialViewLoggedInProcessCompose,            // The dialog view to delete or send the clicked pre-saved text
     //
     FlipSocialViewLoggedInSignOut, // The view after clicking the sign out button
     //
     FlipSocialViewLoggedInExploreSubmenu,  // The view after clicking the explore button
-    FlipSocialViewLoggedInExploreProccess, // The view after clicking on a user in the explore screen
     FlipSocialViewLoggedInFriendsSubmenu,  // The view after clicking the friends button on the profile screen
-    FlipSocialViewLoggedInFriendsProcess,  // The view after clicking on a friend in the friends screen
     FlipSocialViewLoggedInMessagesSubmenu, // The view after clicking the messages button on the profile screen
-    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
+    //
+    FlipSocialViewExploreDialog,  // The dialog for the explore screen
+    FlipSocialViewFriendsDialog,  // The dialog for the friends screen
+    FlipSocialViewMessagesDialog, // The dialog for the messages screen
+    FlipSocialViewComposeDialog,  // The dialog for the compose screen
+    FlipSocialViewFeedDialog,     // The dialog for the feed screen
 } 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)
@@ -156,14 +172,6 @@ typedef struct
     Widget *widget_logged_out_about;        // The about screen (logged out)
     Widget *widget_logged_in_about;         // The about screen (logged in)
 
-    View *view_process_login;    // The screen displayed after clicking login
-    View *view_process_register; // The screen displayed after clicking register
-    View *view_process_feed;     // Dialog for the feed screen
-    View *view_process_compose;  // Dialog for the compose screen (delete or send)
-    View *view_process_explore;  // Dialog for the explore screen (view user profile - add or delete friend)
-    View *view_process_friends;  // Dialog for the friends screen (view user profile - add or delete friend)
-    View *view_process_messages; // Dialog for the messages screen (next, previous, send message)
-
     VariableItemList *variable_item_list_logged_out_wifi_settings; // The wifi settings menu
     VariableItemList *variable_item_list_logged_out_login;         // The login menu
     VariableItemList *variable_item_list_logged_out_register;      // The register menu
@@ -272,16 +280,23 @@ typedef struct
     char *message_user_choice_logged_in;                     // Store the entered message to send to the selected user
     char *message_user_choice_logged_in_temp_buffer;         // Temporary buffer for message to send to the selected user
     uint32_t message_user_choice_logged_in_temp_buffer_size; // Size of the message to send to the selected user temporary buffer
+
+    Loading *loading; // The loading screen
+    DialogEx *dialog_explore;
+    DialogEx *dialog_friends;
+    DialogEx *dialog_messages;
+    DialogEx *dialog_compose;
+    DialogEx *dialog_feed;
 } FlipSocialApp;
 
 void flip_social_app_free(FlipSocialApp *app);
 
-extern FlipSocialFeed *flip_social_feed;            // Store the feed
 extern FlipSocialModel *flip_social_friends;        // Store the friends
 extern FlipSocialModel2 *flip_social_message_users; // Store the users that have sent messages to the logged in user
 extern FlipSocialModel *flip_social_explore;        // Store the users to explore
 extern FlipSocialMessage *flip_social_messages;     // Store the messages between the logged in user and the selected user
-
+extern FlipSocialFeedMini *flip_feed_info;          // Store the feed info
+extern FlipSocialFeedItem *flip_feed_item;          // Store a feed item
 extern FlipSocialApp *app_instance;
 
 extern bool flip_social_sent_login_request;
@@ -296,4 +311,6 @@ extern char *selected_message;
 extern char auth_headers[256];
 
 void auth_headers_alloc(void);
+FlipSocialFeedMini *flip_feed_info_alloc(void);
+void flip_feed_info_free(void);
 #endif

+ 31 - 0
flip_storage/flip_social_storage.c

@@ -369,3 +369,34 @@ bool load_settings(
 
     return true;
 }
+
+bool flip_social_save_post(char *post_id, char *json_feed_data)
+{
+    Storage *storage = furi_record_open(RECORD_STORAGE);
+    File *file = storage_file_alloc(storage);
+
+    char file_path[128];
+    snprintf(file_path, sizeof(file_path), STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/feed_post_%s.json", post_id);
+
+    if (!storage_file_open(file, file_path, FSAM_WRITE, FSOM_CREATE_ALWAYS))
+    {
+        FURI_LOG_E(TAG, "Failed to open file for writing: %s", file_path);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return false;
+    }
+
+    if (storage_file_write(file, json_feed_data, strlen(json_feed_data)) != strlen(json_feed_data))
+    {
+        FURI_LOG_E(TAG, "Failed to write feed post data");
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return false;
+    }
+
+    storage_file_close(file);
+    storage_file_free(file);
+    furi_record_close(RECORD_STORAGE);
+    return true;
+}

+ 1 - 0
flip_storage/flip_social_storage.h

@@ -34,4 +34,5 @@ bool load_settings(
     char *is_logged_in,
     size_t is_logged_in_size);
 
+bool flip_social_save_post(char *post_id, char *json_feed_data);
 #endif

+ 128 - 0
flipper_http/flipper_http.c

@@ -1466,4 +1466,132 @@ bool flipper_http_process_response_async(bool (*http_request)(void), bool (*pars
         return false;
     }
     return true;
+}
+bool flipper_http_process_response_async_2(bool (*http_request)(void), int (*parse_json)(void))
+{
+    if (http_request()) // start the async request
+    {
+        furi_timer_start(fhttp.get_timeout_timer, TIMEOUT_DURATION_TICKS);
+        fhttp.state = RECEIVING;
+    }
+    else
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to send request");
+        return false;
+    }
+    while (fhttp.state == RECEIVING && furi_timer_is_running(fhttp.get_timeout_timer) > 0)
+    {
+        // Wait for the request to be received
+        furi_delay_ms(100);
+    }
+    furi_timer_stop(fhttp.get_timeout_timer);
+    if (parse_json() < 1) // parse the JSON before switching to the view (synchonous)
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to parse the JSON...");
+        return false;
+    }
+    return true;
+}
+
+/**
+ * @brief Perform a task while displaying a loading screen
+ * @param http_request The function to send the request
+ * @param parse_response The function to parse the response
+ * @param success_view_id The view ID to switch to on success
+ * @param failure_view_id The view ID to switch to on failure
+ * @param view_dispatcher The view dispatcher to use
+ * @return
+ */
+void flipper_http_loading_task(bool (*http_request)(void),
+                               bool (*parse_response)(void),
+                               uint32_t success_view_id,
+                               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
+
+    loading = loading_alloc();
+    if (!loading)
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to allocate loading");
+        view_dispatcher_switch_to_view(*view_dispatcher, failure_view_id);
+
+        return;
+    }
+
+    view_dispatcher_add_view(*view_dispatcher, loading_view_id, loading_get_view(loading));
+
+    // Switch to the loading view
+    view_dispatcher_switch_to_view(*view_dispatcher, loading_view_id);
+
+    // Make the request
+    if (!flipper_http_process_response_async(http_request, parse_response))
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to make request");
+        view_dispatcher_switch_to_view(*view_dispatcher, failure_view_id);
+        view_dispatcher_remove_view(*view_dispatcher, loading_view_id);
+        loading_free(loading);
+
+        return;
+    }
+
+    // Switch to the success view
+    view_dispatcher_switch_to_view(*view_dispatcher, success_view_id);
+    view_dispatcher_remove_view(*view_dispatcher, loading_view_id);
+    // loading_free(loading);
+}
+
+/**
+ * @brief Perform a task while displaying a loading screen
+ * @param http_request The function to send the request
+ * @param parse_response The function to parse the response
+ * @param success_view_id The view ID to switch to on success
+ * @param failure_view_id The view ID to switch to on failure
+ * @param view_dispatcher The view dispatcher to use
+ * @return
+ */
+void flipper_http_loading_task_2(bool (*http_request)(void),
+                                 int (*parse_response)(void),
+                                 uint32_t success_view_id,
+                                 uint32_t failure_view_id,
+                                 ViewDispatcher **view_dispatcher)
+{
+    Loading *loading;
+    int32_t loading_view_id = 987654321; // Random ID
+
+    loading = loading_alloc();
+    if (!loading)
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to allocate loading");
+        view_dispatcher_switch_to_view(*view_dispatcher, failure_view_id);
+
+        return;
+    }
+
+    view_dispatcher_add_view(*view_dispatcher, loading_view_id, loading_get_view(loading));
+
+    // Switch to the loading view
+    view_dispatcher_switch_to_view(*view_dispatcher, loading_view_id);
+
+    // Make the request
+    if (!flipper_http_process_response_async_2(http_request, parse_response))
+    {
+        FURI_LOG_E(HTTP_TAG, "Failed to make request");
+        view_dispatcher_switch_to_view(*view_dispatcher, failure_view_id);
+        view_dispatcher_remove_view(*view_dispatcher, loading_view_id);
+        loading_free(loading);
+
+        return;
+    }
+
+    // Switch to the success view
+    view_dispatcher_switch_to_view(*view_dispatcher, success_view_id);
+    view_dispatcher_remove_view(*view_dispatcher, loading_view_id);
+    loading_free(loading);
 }

+ 39 - 4
flipper_http/flipper_http.h

@@ -2,6 +2,10 @@
 #ifndef FLIPPER_HTTP_H
 #define FLIPPER_HTTP_H
 
+#include <gui/gui.h>
+#include <gui/view.h>
+#include <gui/view_dispatcher.h>
+#include <gui/modules/loading.h>
 #include <furi.h>
 #include <furi_hal.h>
 #include <furi_hal_gpio.h>
@@ -13,11 +17,11 @@
 #define HTTP_TAG "FlipSocial"             // change this to your app name
 #define http_tag "flip_social"            // change this to your app id
 #define UART_CH (FuriHalSerialIdUsart)    // UART channel
-#define TIMEOUT_DURATION_TICKS (5 * 1000) // 5 seconds
+#define TIMEOUT_DURATION_TICKS (8 * 1000) // 8 seconds (increased for Pico W)
 #define BAUDRATE (115200)                 // UART baudrate
-#define RX_BUF_SIZE 1024                  // UART RX buffer size
-#define RX_LINE_BUFFER_SIZE 8192          // UART RX line buffer size (increase for large responses)
-#define MAX_FILE_SHOW 8192                // Maximum data from file to show
+#define RX_BUF_SIZE 128                   // UART RX buffer size
+#define RX_LINE_BUFFER_SIZE 7000          // UART RX line buffer size (increase for large responses)
+#define MAX_FILE_SHOW 7000                // Maximum data from file to show
 #define FILE_BUFFER_SIZE 512              // File buffer size
 
 // Forward declaration for callback
@@ -362,5 +366,36 @@ char *trim(const char *str);
  * @return true if successful, false otherwise
  */
 bool flipper_http_process_response_async(bool (*http_request)(void), bool (*parse_json)(void));
+bool flipper_http_process_response_async_2(bool (*http_request)(void), int (*parse_json)(void));
+
+/**
+ * @brief Perform a task while displaying a loading screen
+ * @param http_request The function to send the request
+ * @param parse_response The function to parse the response
+ * @param success_view_id The view ID to switch to on success
+ * @param failure_view_id The view ID to switch to on failure
+ * @param view_dispatcher The view dispatcher to use
+ * @return
+ */
+void flipper_http_loading_task(bool (*http_request)(void),
+                               bool (*parse_response)(void),
+                               uint32_t success_view_id,
+                               uint32_t failure_view_id,
+                               ViewDispatcher **view_dispatcher);
+
+/**
+ * @brief Perform a task while displaying a loading screen
+ * @param http_request The function to send the request
+ * @param parse_response The function to parse the response
+ * @param success_view_id The view ID to switch to on success
+ * @param failure_view_id The view ID to switch to on failure
+ * @param view_dispatcher The view dispatcher to use
+ * @return
+ */
+void flipper_http_loading_task_2(bool (*http_request)(void),
+                                 int (*parse_response)(void),
+                                 uint32_t success_view_id,
+                                 uint32_t failure_view_id,
+                                 ViewDispatcher **view_dispatcher);
 
 #endif // FLIPPER_HTTP_H

+ 19 - 29
friends/flip_social_friends.c

@@ -19,36 +19,30 @@ FlipSocialModel *flip_social_friends_alloc()
     return friends;
 }
 
-void flip_social_free_friends()
+// for now we're just listing the current users
+// as the feed is upgraded, then we can port more to the friends view
+bool flip_social_get_friends()
 {
-    if (!flip_social_friends)
+    if (!app_instance)
     {
-        FURI_LOG_E(TAG, "Friends model is NULL");
-        return;
+        FURI_LOG_E(TAG, "App instance is NULL");
+        return false;
     }
-    for (int i = 0; i < flip_social_friends->count; i++)
+    if (fhttp.state == INACTIVE)
     {
-        if (flip_social_friends->usernames[i])
-        {
-            free(flip_social_friends->usernames[i]);
-        }
+        FURI_LOG_E(TAG, "HTTP state is INACTIVE");
+        return false;
     }
-}
-
-// for now we're just listing the current users
-// as the feed is upgraded, then we can port more to the friends view
-bool flip_social_get_friends()
-{
     // will return true unless the devboard is not connected
     char url[100];
     snprintf(
         fhttp.file_path,
         sizeof(fhttp.file_path),
-        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/friends.txt");
+        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/friends.json");
 
     fhttp.save_received_data = true;
     auth_headers_alloc();
-    snprintf(url, 100, "https://www.flipsocial.net/api/user/friends/%s/", app_instance->login_username_logged_in);
+    snprintf(url, sizeof(url), "https://www.flipsocial.net/api/user/friends/%s/", app_instance->login_username_logged_in);
     if (!flipper_http_get_request_with_headers(url, auth_headers))
     {
         FURI_LOG_E(TAG, "Failed to send HTTP request for friends");
@@ -118,6 +112,10 @@ bool flip_social_parse_json_friends()
     // Initialize friends count
     flip_social_friends->count = 0;
 
+    // Reset the friends submenu
+    submenu_reset(app_instance->submenu_friends);
+    submenu_set_header(app_instance->submenu_friends, "Friends");
+
     // Extract the users array from the JSON
     char *json_users = get_json_value("friends", data_cstr, MAX_TOKENS);
     if (json_users == NULL)
@@ -143,6 +141,7 @@ bool flip_social_parse_json_friends()
 
         // Copy username to pre-allocated memory
         snprintf(flip_social_friends->usernames[flip_social_friends->count], MAX_USER_LENGTH, "%s", start);
+        submenu_add_item(app_instance->submenu_friends, flip_social_friends->usernames[flip_social_friends->count], FlipSocialSubmenuLoggedInIndexFriendsStart + flip_social_friends->count, flip_social_callback_submenu_choices, app_instance);
         flip_social_friends->count++;
         start = end + 1;
     }
@@ -158,23 +157,14 @@ bool flip_social_parse_json_friends()
             *(start + strlen(start) - 1) = '\0';
 
         snprintf(flip_social_friends->usernames[flip_social_friends->count], MAX_USER_LENGTH, "%s", start);
+        submenu_add_item(app_instance->submenu_friends, flip_social_friends->usernames[flip_social_friends->count], FlipSocialSubmenuLoggedInIndexFriendsStart + flip_social_friends->count, flip_social_callback_submenu_choices, app_instance);
         flip_social_friends->count++;
     }
 
-    // Add submenu items for the friends
-    if (!flip_social_update_friends())
-    {
-        FURI_LOG_E(TAG, "Failed to update friends submenu");
-        furi_string_free(friend_data);
-        free(data_cstr);
-        return false;
-    }
-
-    // Free the json_users
+    furi_string_free(friend_data);
+    free(data_cstr);
     free(json_users);
     free(start);
     free(end);
-    furi_string_free(friend_data);
-    free(data_cstr);
     return true;
 }

+ 0 - 1
friends/flip_social_friends.h

@@ -4,7 +4,6 @@
 #include <callback/flip_social_callback.h>
 
 FlipSocialModel *flip_social_friends_alloc();
-void flip_social_free_friends();
 bool flip_social_get_friends();
 bool flip_social_update_friends();
 bool flip_social_parse_json_friends();

+ 39 - 24
messages/flip_social_messages.c

@@ -2,6 +2,13 @@
 
 FlipSocialModel2 *flip_social_messages_alloc()
 {
+    if (!app_instance->submenu_messages)
+    {
+        if (!easy_flipper_set_submenu(&app_instance->submenu_messages, FlipSocialViewLoggedInMessagesSubmenu, "Messages", flip_social_callback_to_submenu_logged_in, &app_instance->view_dispatcher))
+        {
+            return NULL;
+        }
+    }
     // Allocate memory for each username only if not already allocated
     FlipSocialModel2 *users = malloc(sizeof(FlipSocialModel2));
     if (users == NULL)
@@ -61,36 +68,26 @@ void flip_social_free_message_users()
 {
     if (flip_social_message_users == NULL)
     {
-        FURI_LOG_E(TAG, "Message users model is NULL");
         return;
     }
-    for (int i = 0; i < flip_social_message_users->count; i++)
-    {
-        if (flip_social_message_users->usernames[i])
-        {
-            free(flip_social_message_users->usernames[i]);
-        }
-    }
+    free(flip_social_message_users);
+    flip_social_message_users = NULL;
 }
 
 void flip_social_free_messages()
 {
-    if (flip_social_messages == NULL)
+    if (app_instance->submenu_messages)
     {
-        FURI_LOG_E(TAG, "Messages model is NULL");
-        return;
+        submenu_free(app_instance->submenu_messages);
+        app_instance->submenu_messages = NULL;
+        view_dispatcher_remove_view(app_instance->view_dispatcher, FlipSocialViewLoggedInMessagesSubmenu);
     }
-    for (int i = 0; i < flip_social_messages->count; i++)
+    if (flip_social_messages == NULL)
     {
-        if (flip_social_messages->usernames[i])
-        {
-            free(flip_social_messages->usernames[i]);
-        }
-        if (flip_social_messages->messages[i])
-        {
-            free(flip_social_messages->messages[i]);
-        }
+        return;
     }
+    free(flip_social_messages);
+    flip_social_messages = NULL;
 }
 
 bool flip_social_update_messages_submenu()
@@ -144,11 +141,16 @@ 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,
         sizeof(fhttp.file_path),
-        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/message_users.txt");
+        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/message_users.json");
 
     fhttp.save_received_data = true;
     auth_headers_alloc();
@@ -166,6 +168,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");
@@ -180,7 +187,8 @@ bool flip_social_get_messages_with_user()
     snprintf(
         fhttp.file_path,
         sizeof(fhttp.file_path),
-        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/messages.txt");
+        STORAGE_EXT_PATH_PREFIX "/apps_data/flip_social/%s_messages.json",
+        flip_social_message_users->usernames[flip_social_message_users->index]);
 
     fhttp.save_received_data = true;
     auth_headers_alloc();
@@ -430,8 +438,8 @@ bool flip_social_parse_json_messages()
         }
 
         // Extract individual fields from the JSON object
-        char *sender = get_json_value("sender", item, MAX_TOKENS);
-        char *content = get_json_value("content", item, MAX_TOKENS);
+        char *sender = get_json_value("sender", item, 64);
+        char *content = get_json_value("content", item, 64);
 
         if (sender == NULL || content == NULL)
         {
@@ -449,6 +457,13 @@ bool flip_social_parse_json_messages()
         free(sender);
         free(content);
     }
+    if (!messages_dialog_alloc(true))
+    {
+        FURI_LOG_E(TAG, "Failed to allocate and set messages dialog.");
+        furi_string_free(message_data);
+        free(data_cstr);
+        return false;
+    }
     furi_string_free(message_data);
     free(data_cstr);
     return true;

Некоторые файлы не были показаны из-за большого количества измененных файлов