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

FlipSocial - v0.2 (Stability Patch)

jblanked 1 год назад
Родитель
Сommit
3ae8d71935
12 измененных файлов с 1882 добавлено и 1177 удалено
  1. BIN
      .DS_Store
  2. 4 1
      README.md
  3. 1 1
      application.fam
  4. 4 1
      assets/README.md
  5. 593 0
      easy_flipper.h
  6. 178 545
      flip_social_callback.h
  7. 18 12
      flip_social_e.h
  8. 266 0
      flip_social_feed.h
  9. 311 252
      flip_social_i.h
  10. 0 2
      flip_social_storage.h
  11. 3 3
      flipper_http.h
  12. 504 360
      jsmn.h

+ 4 - 1
README.md

@@ -1,6 +1,10 @@
 # FlipSocial
 The first social media app for Flipper Zero. Connect with other users directly on your device through WiFi. The highlight of this app is customizable pre-saves, which, as explained below, aim to solve the dissatisfaction of typing with the directional pad. FlipSocial uses the FlipperHTTP flash for the WiFi Devboard, first introduced in the WebCrawler app: https://github.com/jblanked/WebCrawler-FlipperZero/tree/main/assets/FlipperHTTP
 
+## Requirements
+- WiFi Dev Board for Flipper Zero with FlipperHTTP Flash: https://github.com/jblanked/WebCrawler-FlipperZero/tree/main/assets/FlipperHTTP
+- WiFi Access Point
+
 ## Features
 - Login/Logout
 - Registration
@@ -24,7 +28,6 @@ The biggest challenge with a social media app on the Flipper Zero is using only
 ## Roadmap
 **v0.2**
 - Stability Patch
-- LED options
 
 **v0.3**
 - Explore Page

+ 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.1",
+    fap_version="0.2",
     fap_description="Social media platform for the Flipper Zero.",
 )

+ 4 - 1
assets/README.md

@@ -1,6 +1,10 @@
 # FlipSocial
 The first social media app for Flipper Zero. Connect with other users directly on your device through WiFi. The highlight of this app is customizable pre-saves, which, as explained below, aim to solve the dissatisfaction of typing with the directional pad. FlipSocial uses the FlipperHTTP flash for the WiFi Devboard, first introduced in the WebCrawler app: https://github.com/jblanked/WebCrawler-FlipperZero/tree/main/assets/FlipperHTTP
 
+## Requirements
+- WiFi Dev Board for Flipper Zero with FlipperHTTP Flash: https://github.com/jblanked/WebCrawler-FlipperZero/tree/main/assets/FlipperHTTP
+- WiFi Access Point
+
 ## Features
 - Login/Logout
 - Registration
@@ -24,7 +28,6 @@ The biggest challenge with a social media app on the Flipper Zero is using only
 ## Roadmap
 **v0.2**
 - Stability Patch
-- LED options
 
 **v0.3**
 - Explore Page

+ 593 - 0
easy_flipper.h

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

+ 178 - 545
flip_social_callback.h

@@ -1,254 +1,121 @@
 // flip_social_callback.h
 #ifndef FLIP_SOCIAL_CALLBACK_H
 #define FLIP_SOCIAL_CALLBACK_H
-static FlipSocialApp *app_instance = NULL;
+#include "flip_social_feed.h"
+
 bool flip_social_sent_login_request = false;
 bool flip_social_sent_register_request = false;
 bool flip_social_login_success = false;
 bool flip_social_register_success = false;
 bool flip_social_dialog_shown = false;
 bool flip_social_dialog_stop = false;
+
 uint32_t flip_social_pre_saved_message_clicked_index = 0;
 static void flip_social_logged_in_compose_pre_save_updated(void *context);
 static void flip_social_callback_submenu_choices(void *context, uint32_t index);
-// include strndup
-char *strndup(const char *s, size_t n)
-{
-    char *result;
-    size_t len = strlen(s);
 
-    if (n < len)
-        len = n;
-
-    result = (char *)malloc(len + 1);
-    if (!result)
-        return NULL;
-
-    result[len] = '\0';
-    return (char *)memcpy(result, s, len);
+/**
+ * @brief Navigation callback to go back to the submenu Logged out.
+ * @param context The context - unused
+ * @return next view id (FlipSocialViewLoggedOutSubmenu)
+ */
+static uint32_t flip_social_callback_to_submenu_logged_out(void *context)
+{
+    UNUSED(context);
+    return FlipSocialViewLoggedOutSubmenu;
 }
 
-typedef struct
-{
-    char *usernames[128];
-    char *messages[128];
-    bool is_flipped[128];
-    uint32_t ids[128];
-    size_t count;
-    size_t index;
-} FlipSocialFeed;
-
-#define MAX_FEED_ITEMS 128
-#define MAX_LINE_LENGTH 30
-
-// temporary FlipSocialFeed object
-static FlipSocialFeed flip_social_feed = {
-    .usernames = {"JBlanked", "FlipperKing", "FlipperQueen"},
-    .messages = {"Welcome. This is a temp message. Either the feed didn't load or there was a server error.", "I am the Chosen Flipper.", "No one can flip like me."},
-    .is_flipped = {false, false, true},
-    .ids = {0, 1, 2},
-    .count = 3,
-    .index = 0};
-
-bool flip_social_get_feed()
+/**
+ * @brief Navigation callback to go back to the submenu Logged in.
+ * @param context The context - unused
+ * @return next view id (FlipSocialViewLoggedInSubmenu)
+ */
+static uint32_t flip_social_callback_to_submenu_logged_in(void *context)
 {
-    // Get the feed from the server
-    if (app_instance->login_username_logged_out == NULL)
-    {
-        FURI_LOG_E(TAG, "Username is NULL");
-        return false;
-    }
-    char command[256];
-    snprintf(command, 128, "https://www.flipsocial.net/api/feed/20/%s/", app_instance->login_username_logged_out);
-    bool success = flipper_http_get_request_with_headers(command, "{\"Content-Type\":\"application/json\"}");
-    if (!success)
-    {
-        FURI_LOG_E(TAG, "Failed to send HTTP request for feed");
-        return false;
-    }
-    fhttp.state = RECEIVING;
-    return true;
+    UNUSED(context);
+    // flip_social_get_feed(); // start the feed request
+    return FlipSocialViewLoggedInSubmenu;
 }
 
-#define MAX_TOKENS 128 // Adjust based on expected JSON size
-
-// Helper function to compare JSON keys
-int jsoneq(const char *json, jsmntok_t *tok, const char *s)
+/**
+ * @brief Navigation callback to bring the user back to the (Logged out) Login screen
+ * @param context The context - unused
+ * @return next view id (FlipSocialViewLoggedOutLogin)
+ */
+static uint32_t flip_social_callback_to_login_logged_out(void *context)
 {
-    if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start &&
-        strncmp(json + tok->start, s, tok->end - tok->start) == 0)
-    {
-        return 0;
-    }
-    return -1;
+    UNUSED(context);
+    flip_social_sent_login_request = false;
+    flip_social_login_success = false;
+    return FlipSocialViewLoggedOutLogin;
 }
 
-bool flip_social_parse_json_feed()
+/**
+ * @brief Navigation callback to bring the user back to the (Logged out) Register screen
+ * @param context The context - unused
+ * @return next view id (FlipSocialViewLoggedOutRegister)
+ */
+static uint32_t flip_social_callback_to_register_logged_out(void *context)
 {
-    // Parse the JSON feed
-    if (fhttp.received_data != NULL)
-    {
-        jsmn_parser parser;
-        jsmn_init(&parser);
-
-        // Allocate tokens array on the heap
-        jsmntok_t *tokens = malloc(sizeof(jsmntok_t) * MAX_TOKENS);
-        if (tokens == NULL)
-        {
-            FURI_LOG_E(TAG, "Failed to allocate memory for JSON tokens.");
-            return false;
-        }
-
-        int ret = jsmn_parse(&parser, fhttp.received_data, strlen(fhttp.received_data), tokens, MAX_TOKENS);
-
-        if (ret < 0)
-        {
-            // Handle parsing errors
-            FURI_LOG_E(TAG, "Failed to parse JSON: %d", ret);
-            free(tokens);
-            return false;
-        }
-
-        // Ensure that the root element is an object
-        if (ret < 1 || tokens[0].type != JSMN_OBJECT)
-        {
-            FURI_LOG_E(TAG, "Root element is not an object.");
-            free(tokens);
-            return false;
-        }
-
-        // Initialize feed count
-        flip_social_feed.count = 0;
-
-        // Loop over all keys in the root object
-        int i = 0;
-        for (i = 1; i < ret; i++)
-        {
-            if (jsoneq(fhttp.received_data, &tokens[i], "feed") == 0)
-            {
-                // Found "feed" key
-                jsmntok_t *feed_array = &tokens[i + 1];
+    UNUSED(context);
+    flip_social_sent_register_request = false;
+    flip_social_register_success = false;
+    return FlipSocialViewLoggedOutRegister;
+}
 
-                if (feed_array->type != JSMN_ARRAY)
-                {
-                    FURI_LOG_E(TAG, "'feed' is not an array.");
-                    break;
-                }
+/**
+ * @brief Navigation callback to bring the user back to the (Logged out) Wifi Settings screen
+ * @param context The context - unused
+ * @return next view id (FlipSocialViewLoggedOutWifiSettings)
+ */
+static uint32_t flip_social_callback_to_wifi_settings_logged_out(void *context)
+{
+    UNUSED(context);
+    return FlipSocialViewLoggedOutWifiSettings;
+}
 
-                int j, k;
-                int feed_index = 0;
+/**
+ * @brief Navigation callback to bring the user back to the (Logged in) Wifi Settings screen
+ * @param context The context - unused
+ * @return next view id (FlipSocialViewLoggedInSettingsWifi)
+ */
+static uint32_t flip_social_callback_to_wifi_settings_logged_in(void *context)
+{
+    UNUSED(context);
+    return FlipSocialViewLoggedInSettingsWifi;
+}
 
-                // Iterate over the feed array
-                for (j = 0; j < feed_array->size; j++)
-                {
-                    int idx = i + 2; // Position of the first feed item
-                    for (k = 0; k < j; k++)
-                    {
-                        // Skip tokens of previous feed items
-                        idx += tokens[idx].size * 2 + 1;
-                    }
-
-                    if (idx >= ret)
-                    {
-                        FURI_LOG_E(TAG, "Index out of bounds while accessing feed items.");
-                        break;
-                    }
-
-                    jsmntok_t *item = &tokens[idx];
-                    if (item->type != JSMN_OBJECT)
-                    {
-                        FURI_LOG_E(TAG, "Feed item is not an object.");
-                        continue;
-                    }
-
-                    // Variables to hold item data
-                    char *username = NULL;
-                    char *message = NULL;
-                    int flipped = 0;
-                    int id = 0;
-
-                    // Iterate over keys in the feed item
-                    int l;
-                    int item_size = item->size;
-                    int item_idx = idx + 1; // Position of the first key in the item
-
-                    for (l = 0; l < item_size; l++)
-                    {
-                        if (item_idx + 1 >= ret)
-                        {
-                            FURI_LOG_E(TAG, "Index out of bounds while accessing item properties.");
-                            break;
-                        }
-
-                        jsmntok_t *key = &tokens[item_idx];
-                        jsmntok_t *val = &tokens[item_idx + 1];
-
-                        if (jsoneq(fhttp.received_data, key, "username") == 0)
-                        {
-                            username = strndup(fhttp.received_data + val->start, val->end - val->start);
-                        }
-                        else if (jsoneq(fhttp.received_data, key, "message") == 0)
-                        {
-                            message = strndup(fhttp.received_data + val->start, val->end - val->start);
-                        }
-                        else if (jsoneq(fhttp.received_data, key, "flipped") == 0)
-                        {
-                            if (val->type == JSMN_PRIMITIVE)
-                            {
-                                if (strncmp(fhttp.received_data + val->start, "true", val->end - val->start) == 0)
-                                    flipped = 1;
-                                else
-                                    flipped = 0;
-                            }
-                        }
-                        else if (jsoneq(fhttp.received_data, key, "id") == 0)
-                        {
-                            if (val->type == JSMN_PRIMITIVE)
-                            {
-                                char id_str[16] = {0};
-                                uint32_t id_len = val->end - val->start;
-                                if (id_len >= sizeof(id_str))
-                                    id_len = sizeof(id_str) - 1;
-                                strncpy(id_str, fhttp.received_data + val->start, id_len);
-                                id = atoi(id_str);
-                            }
-                        }
-
-                        item_idx += 2; // Move to the next key-value pair
-                    }
-
-                    // Store the data in flip_social_feed
-                    if (username && message && feed_index < MAX_FEED_ITEMS)
-                    {
-                        flip_social_feed.usernames[feed_index] = username;
-                        flip_social_feed.messages[feed_index] = message;
-                        flip_social_feed.is_flipped[feed_index] = flipped;
-                        flip_social_feed.ids[feed_index] = id;
-                        feed_index++;
-                        flip_social_feed.count = feed_index;
-                    }
-                    else
-                    {
-                        // Free allocated memory if not stored
-                        if (username)
-                            free(username);
-                        if (message)
-                            free(message);
-                    }
-                }
-                break; // Feed processed
-            }
-        }
+/**
+ * @brief Navigation callback to bring the user back to the (Logged in) Settings screen
+ * @param context The context - unused
+ * @return next view id (FlipSocialViewLoggedInSettingsWifi)
+ */
+static uint32_t flip_social_callback_to_settings_logged_in(void *context)
+{
+    UNUSED(context);
+    return FlipSocialViewLoggedInSettings;
+}
 
-        free(tokens); // Free the allocated tokens array
-    }
-    else
-    {
-        FURI_LOG_E(TAG, "No data received.");
-        return false;
-    }
+/**
+ * @brief Navigation callback to bring the user back to the (Logged in) Compose screen
+ * @param context The context - unused
+ * @return next view id (FlipSocialViewLoggedInCompose)
+ */
+static uint32_t flip_social_callback_to_compose_logged_in(void *context)
+{
+    UNUSED(context);
+    return FlipSocialViewLoggedInCompose;
+}
 
-    return true;
+/**
+ * @brief Navigation callback to bring the user back to the (Logged in) Profile screen
+ * @param context The context - unused
+ * @return next view id (FlipSocialViewLoggedInProfile)
+ */
+static uint32_t flip_social_callback_to_profile_logged_in(void *context)
+{
+    UNUSED(context);
+    return FlipSocialViewLoggedInProfile;
 }
 
 static void on_input(const void *event, void *ctx)
@@ -321,16 +188,12 @@ void draw_user_message(Canvas *canvas, const char *user_message, int x)
             {
                 len = last_space; // Adjust len to the position of the last space
             }
-            // If no space is found, len remains MAX_LINE_LENGTH to force split
         }
 
         // Copy the substring to 'line' and null-terminate it
         memcpy(line, user_message + start, len);
         line[len] = '\0'; // Ensure the string is null-terminated
 
-        // Debug Logging: Print the current line being drawn
-        FURI_LOG_D(TAG, "Drawing line %d: \"%s\"", line_num + 1, line);
-
         // Draw the string on the canvas
         // Adjust the y-coordinate based on the line number
         canvas_draw_str_aligned(canvas, 0, x + line_num * 10, AlignLeft, AlignTop, line);
@@ -347,12 +210,6 @@ void draw_user_message(Canvas *canvas, const char *user_message, int x)
         // Increment the line number
         line_num++;
     }
-
-    // Handle any remaining text that wasn't processed due to exceeding MAX_FEED_ITEMS
-    if (start < msg_length)
-    {
-        FURI_LOG_E(TAG, "Message exceeds maximum number of lines (%d).", MAX_FEED_ITEMS);
-    }
 }
 
 static void flip_social_callback_draw_compose(Canvas *canvas, void *model)
@@ -400,7 +257,7 @@ static void flip_social_callback_draw_compose(Canvas *canvas, void *model)
         if (message && app_instance->login_username_logged_in)
         {
             // Send the message
-            char command[256];
+            char command[128];
             snprintf(command, sizeof(command), "{\"username\":\"%s\",\"content\":\"%s\"}",
                      app_instance->login_username_logged_in, message);
 
@@ -432,7 +289,7 @@ static void flip_social_callback_draw_compose(Canvas *canvas, void *model)
             // Wait for the feed to be received
             furi_delay_ms(100);
 
-            char dots_str[256] = "Receiving";
+            char dots_str[64] = "Receiving";
 
             // Append dots to the string based on the value of i
             int dot_count = i % 4;
@@ -623,14 +480,8 @@ static void flip_social_callback_draw_login(Canvas *canvas, void *model)
 
     canvas_set_font(canvas, FontSecondary);
 
-    if (fhttp.state == INACTIVE)
+    if (!flip_social_board_is_active(canvas))
     {
-        canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
-        canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
-        canvas_draw_str(canvas, 0, 32, "If your board is connected,");
-        canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
-        canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
-        canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
         return;
     }
 
@@ -653,7 +504,16 @@ static void flip_social_callback_draw_login(Canvas *canvas, void *model)
         char buffer[256];
         snprintf(buffer, sizeof(buffer), "{\"username\":\"%s\",\"password\":\"%s\"}", app_instance->login_username_logged_out, app_instance->login_password_logged_out);
         flip_social_login_success = flipper_http_post_request_with_headers("https://www.flipsocial.net/api/login/", "{\"Content-Type\":\"application/json\"}", buffer);
-        fhttp.state = RECEIVING;
+        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)
@@ -683,50 +543,18 @@ static void flip_social_callback_draw_login(Canvas *canvas, void *model)
                 canvas_draw_str(canvas, 0, 10, "Account not found...");
                 canvas_draw_str(canvas, 0, 60, "Press BACK to return.");
             }
-            else if (strstr(fhttp.received_data, "[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.received_data, "[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, "Login failed...");
-                canvas_draw_str(canvas, 0, 52, "Update your credentials.");
-                canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
+                flip_social_handle_error(canvas);
             }
         }
         else if ((fhttp.state == ISSUE || fhttp.state == INACTIVE) && fhttp.received_data != NULL)
         {
-            if (strstr(fhttp.received_data, "[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.received_data, "[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
-            {
-                FURI_LOG_E(TAG, "Received an error: %s", fhttp.received_data);
-                canvas_draw_str(canvas, 0, 42, "Login failed...");
-                canvas_draw_str(canvas, 0, 52, "Update your credentials.");
-                canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
-            }
+            flip_social_handle_error(canvas);
+        }
+        else if (fhttp.state == IDLE && fhttp.received_data == NULL)
+        {
+            flip_social_handle_error(canvas);
         }
     }
     else if (flip_social_sent_login_request && !flip_social_login_success)
@@ -755,14 +583,8 @@ static void flip_social_callback_draw_register(Canvas *canvas, void *model)
 
     canvas_set_font(canvas, FontSecondary);
 
-    if (fhttp.state == INACTIVE)
+    if (!flip_social_board_is_active(canvas))
     {
-        canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
-        canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
-        canvas_draw_str(canvas, 0, 32, "If you board is connected,");
-        canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
-        canvas_draw_str(canvas, 0, 52, "your Dev Board with the");
-        canvas_draw_str(canvas, 0, 62, "FlipperHTTP firmware.");
         return;
     }
 
@@ -789,13 +611,20 @@ static void flip_social_callback_draw_register(Canvas *canvas, void *model)
             return;
         }
 
-        char buffer[256];
+        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/register/", "{\"Content-Type\":\"application/json\"}", buffer);
 
         flip_social_sent_register_request = true;
-        // Set the state to RECEIVING to ensure we continue to see the receiving message
-        fhttp.state = RECEIVING;
+        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)
@@ -822,6 +651,10 @@ static void flip_social_callback_draw_register(Canvas *canvas, void *model)
                     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";
 
@@ -852,26 +685,7 @@ static void flip_social_callback_draw_register(Canvas *canvas, void *model)
         }
         else if (fhttp.state == ISSUE || fhttp.state == INACTIVE)
         {
-            if (strstr(fhttp.received_data, "[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.received_data, "[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, "Login failed...");
-                canvas_draw_str(canvas, 0, 52, "Update your credentials.");
-                canvas_draw_str(canvas, 0, 62, "Press BACK to return.");
-            }
+            flip_social_handle_error(canvas);
         }
     }
     else if (flip_social_sent_register_request && !flip_social_register_success)
@@ -967,8 +781,7 @@ static void flip_social_callback_submenu_choices(void *context, uint32_t index)
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedOutSubmenu);
         break;
     case FlipSocialSubmenuComposeIndexAddPreSave:
-        uart_text_input_set_header_text(app->text_input_logged_in_compose_pre_save_input, "Enter your message:");
-        uart_text_input_set_result_callback(app->text_input_logged_in_compose_pre_save_input, flip_social_logged_in_compose_pre_save_updated, app, app->compose_pre_save_logged_in_temp_buffer, app->compose_pre_save_logged_in_temp_buffer_size, false);
+
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedInComposeAddPreSaveInput);
         break;
     default:
@@ -980,110 +793,6 @@ static void flip_social_callback_submenu_choices(void *context, uint32_t index)
     }
 }
 
-/**
- * @brief Navigation callback to go back to the submenu Logged out.
- * @param context The context - unused
- * @return next view id (FlipSocialViewLoggedOutSubmenu)
- */
-static uint32_t flip_social_callback_to_submenu_logged_out(void *context)
-{
-    UNUSED(context);
-    return FlipSocialViewLoggedOutSubmenu;
-}
-
-/**
- * @brief Navigation callback to go back to the submenu Logged in.
- * @param context The context - unused
- * @return next view id (FlipSocialViewLoggedInSubmenu)
- */
-static uint32_t flip_social_callback_to_submenu_logged_in(void *context)
-{
-    UNUSED(context);
-    // flip_social_get_feed(); // start the feed request
-    return FlipSocialViewLoggedInSubmenu;
-}
-
-/**
- * @brief Navigation callback to bring the user back to the (Logged out) Login screen
- * @param context The context - unused
- * @return next view id (FlipSocialViewLoggedOutLogin)
- */
-static uint32_t flip_social_callback_to_login_logged_out(void *context)
-{
-    UNUSED(context);
-    flip_social_sent_login_request = false;
-    flip_social_login_success = false;
-    return FlipSocialViewLoggedOutLogin;
-}
-
-/**
- * @brief Navigation callback to bring the user back to the (Logged out) Register screen
- * @param context The context - unused
- * @return next view id (FlipSocialViewLoggedOutRegister)
- */
-static uint32_t flip_social_callback_to_register_logged_out(void *context)
-{
-    UNUSED(context);
-    flip_social_sent_register_request = false;
-    flip_social_register_success = false;
-    return FlipSocialViewLoggedOutRegister;
-}
-
-/**
- * @brief Navigation callback to bring the user back to the (Logged out) Wifi Settings screen
- * @param context The context - unused
- * @return next view id (FlipSocialViewLoggedOutWifiSettings)
- */
-static uint32_t flip_social_callback_to_wifi_settings_logged_out(void *context)
-{
-    UNUSED(context);
-    return FlipSocialViewLoggedOutWifiSettings;
-}
-
-/**
- * @brief Navigation callback to bring the user back to the (Logged in) Wifi Settings screen
- * @param context The context - unused
- * @return next view id (FlipSocialViewLoggedInSettingsWifi)
- */
-static uint32_t flip_social_callback_to_wifi_settings_logged_in(void *context)
-{
-    UNUSED(context);
-    return FlipSocialViewLoggedInSettingsWifi;
-}
-
-/**
- * @brief Navigation callback to bring the user back to the (Logged in) Settings screen
- * @param context The context - unused
- * @return next view id (FlipSocialViewLoggedInSettingsWifi)
- */
-static uint32_t flip_social_callback_to_settings_logged_in(void *context)
-{
-    UNUSED(context);
-    return FlipSocialViewLoggedInSettings;
-}
-
-/**
- * @brief Navigation callback to bring the user back to the (Logged in) Compose screen
- * @param context The context - unused
- * @return next view id (FlipSocialViewLoggedInCompose)
- */
-static uint32_t flip_social_callback_to_compose_logged_in(void *context)
-{
-    UNUSED(context);
-    return FlipSocialViewLoggedInCompose;
-}
-
-/**
- * @brief Navigation callback to bring the user back to the (Logged in) Profile screen
- * @param context The context - unused
- * @return next view id (FlipSocialViewLoggedInProfile)
- */
-static uint32_t flip_social_callback_to_profile_logged_in(void *context)
-{
-    UNUSED(context);
-    return FlipSocialViewLoggedInProfile;
-}
-
 /**
  * @brief Text input callback for when the user finishes entering their SSID on the wifi settings (logged out) screen.
  * @param context The context - FlipSocialApp object.
@@ -1100,6 +809,10 @@ static void flip_social_logged_out_wifi_settings_ssid_updated(void *context)
     // Store the entered name
     strncpy(app->wifi_ssid_logged_out, app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_out_temp_buffer_size);
 
+    // Store the entered name in the logged in name field
+    strncpy(app->wifi_ssid_logged_in, app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_out_temp_buffer_size);
+    strncpy(app->wifi_ssid_logged_in_temp_buffer, app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_out_temp_buffer_size);
+
     // Ensure null-termination
     app->wifi_ssid_logged_out[app->wifi_ssid_logged_out_temp_buffer_size - 1] = '\0';
 
@@ -1135,9 +848,13 @@ static void flip_social_logged_out_wifi_settings_password_updated(void *context)
         FURI_LOG_E(TAG, "FlipSocialApp is NULL");
         return;
     }
-    // Store the entered password
+    // Store the entered WiFi password
     strncpy(app->wifi_password_logged_out, app->wifi_password_logged_out_temp_buffer, app->wifi_password_logged_out_temp_buffer_size);
 
+    // Store the entered WiFi password in the logged in password field
+    strncpy(app->wifi_password_logged_in, app->wifi_password_logged_out_temp_buffer, app->wifi_password_logged_out_temp_buffer_size);
+    strncpy(app->wifi_password_logged_in_temp_buffer, app->wifi_password_logged_out_temp_buffer, app->wifi_password_logged_out_temp_buffer_size);
+
     // Ensure null-termination
     app->wifi_password_logged_out[app->wifi_password_logged_out_temp_buffer_size - 1] = '\0';
 
@@ -1177,31 +894,9 @@ static void flip_social_text_input_logged_out_wifi_settings_item_selected(void *
     switch (index)
     {
     case 0: // Input SSID
-        // Initialize temp_buffer with the current name
-        if (app->wifi_ssid_logged_out && strlen(app->wifi_ssid_logged_out) > 0)
-        {
-            strncpy(app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_out, app->wifi_ssid_logged_out_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->wifi_ssid_logged_out_temp_buffer, "", app->wifi_ssid_logged_out_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_out_wifi_settings_ssid, "Enter SSID");
-        uart_text_input_set_result_callback(app->text_input_logged_out_wifi_settings_ssid, flip_social_logged_out_wifi_settings_ssid_updated, app, app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_out_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedOutWifiSettingsSSIDInput);
         break;
     case 1: // Input Password
-        // Initialize temp_buffer with the current password
-        if (app->wifi_password_logged_out && strlen(app->wifi_password_logged_out) > 0)
-        {
-            strncpy(app->wifi_password_logged_out_temp_buffer, app->wifi_password_logged_out, app->wifi_password_logged_out_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->wifi_password_logged_out_temp_buffer, "", app->wifi_password_logged_out_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_out_wifi_settings_password, "Enter Password");
-        uart_text_input_set_result_callback(app->text_input_logged_out_wifi_settings_password, flip_social_logged_out_wifi_settings_password_updated, app, app->wifi_password_logged_out_temp_buffer, app->wifi_password_logged_out_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedOutWifiSettingsPasswordInput);
         break;
     default:
@@ -1226,6 +921,10 @@ static void flip_social_logged_out_login_username_updated(void *context)
     // Store the entered name
     strncpy(app->login_username_logged_out, app->login_username_logged_out_temp_buffer, app->login_username_logged_out_temp_buffer_size);
 
+    // Store the entered name in the logged in username field
+    strncpy(app->login_username_logged_in, app->login_username_logged_out_temp_buffer, app->login_username_logged_out_temp_buffer_size);
+    strncpy(app->login_username_logged_in_temp_buffer, app->login_username_logged_out_temp_buffer, app->login_username_logged_out_temp_buffer_size);
+
     // Ensure null-termination
     app->login_username_logged_out[app->login_username_logged_out_temp_buffer_size - 1] = '\0';
 
@@ -1258,13 +957,18 @@ static void flip_social_logged_out_login_password_updated(void *context)
     // Store the entered password
     strncpy(app->login_password_logged_out, app->login_password_logged_out_temp_buffer, app->login_password_logged_out_temp_buffer_size);
 
+    // Store the entered password in the change password field
+    strncpy(app->change_password_logged_in, app->login_password_logged_out_temp_buffer, app->login_password_logged_out_temp_buffer_size);
+    strncpy(app->change_password_logged_in_temp_buffer, app->login_password_logged_out_temp_buffer, app->login_password_logged_out_temp_buffer_size);
+
     // Ensure null-termination
     app->login_password_logged_out[app->login_password_logged_out_temp_buffer_size - 1] = '\0';
 
     // Update the password item text
     if (app->variable_item_logged_out_login_password)
     {
-        variable_item_set_current_value_text(app->variable_item_logged_out_login_password, app->login_password_logged_out);
+        // dont show the password on the screen (version 0.2)
+        // variable_item_set_current_value_text(app->variable_item_logged_out_login_password, app->login_password_logged_out);
     }
 
     // Save the settings
@@ -1290,31 +994,9 @@ static void flip_social_text_input_logged_out_login_item_selected(void *context,
     switch (index)
     {
     case 0: // Input Username
-        // Initialize temp_buffer with the current name
-        if (app->login_username_logged_out && strlen(app->login_username_logged_out) > 0)
-        {
-            strncpy(app->login_username_logged_out_temp_buffer, app->login_username_logged_out, app->login_username_logged_out_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->login_username_logged_out_temp_buffer, "", app->login_username_logged_out_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_out_login_username, "Enter Username");
-        uart_text_input_set_result_callback(app->text_input_logged_out_login_username, flip_social_logged_out_login_username_updated, app, app->login_username_logged_out_temp_buffer, app->login_username_logged_out_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedOutLoginUsernameInput);
         break;
     case 1: // Input Password
-        // Initialize temp_buffer with the current password
-        if (app->login_password_logged_out && strlen(app->login_password_logged_out) > 0)
-        {
-            strncpy(app->login_password_logged_out_temp_buffer, app->login_password_logged_out, app->login_password_logged_out_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->login_password_logged_out_temp_buffer, "", app->login_password_logged_out_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_out_login_password, "Enter Password");
-        uart_text_input_set_result_callback(app->text_input_logged_out_login_password, flip_social_logged_out_login_password_updated, app, app->login_password_logged_out_temp_buffer, app->login_password_logged_out_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedOutLoginPasswordInput);
         break;
     case 2: // Login Button
@@ -1427,45 +1109,12 @@ static void flip_social_text_input_logged_out_register_item_selected(void *conte
     switch (index)
     {
     case 0: // Input Username
-        // Initialize temp_buffer with the current name
-        if (app->register_username_logged_out && strlen(app->register_username_logged_out) > 0)
-        {
-            strncpy(app->register_username_logged_out_temp_buffer, app->register_username_logged_out, app->register_username_logged_out_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->register_username_logged_out_temp_buffer, "", app->register_username_logged_out_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_out_register_username, "Enter Username");
-        uart_text_input_set_result_callback(app->text_input_logged_out_register_username, flip_social_logged_out_register_username_updated, app, app->register_username_logged_out_temp_buffer, app->register_username_logged_out_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedOutRegisterUsernameInput);
         break;
     case 1: // Input Password
-        // Initialize temp_buffer with the current password
-        if (app->register_password_logged_out && strlen(app->register_password_logged_out) > 0)
-        {
-            strncpy(app->register_password_logged_out_temp_buffer, app->register_password_logged_out, app->register_password_logged_out_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->register_password_logged_out_temp_buffer, "", app->register_password_logged_out_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_out_register_password, "Enter Password");
-        uart_text_input_set_result_callback(app->text_input_logged_out_register_password, flip_social_logged_out_register_password_updated, app, app->register_password_logged_out_temp_buffer, app->register_password_logged_out_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedOutRegisterPasswordInput);
         break;
     case 2: // Input Password 2
-        // Initialize temp_buffer with the current password
-        if (app->register_password_2_logged_out && strlen(app->register_password_2_logged_out) > 0)
-        {
-            strncpy(app->register_password_2_logged_out_temp_buffer, app->register_password_2_logged_out, app->register_password_2_logged_out_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->register_password_2_logged_out_temp_buffer, "", app->register_password_2_logged_out_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_out_register_password_2, "Enter Password Again");
-        uart_text_input_set_result_callback(app->text_input_logged_out_register_password_2, flip_social_logged_out_register_password_2_updated, app, app->register_password_2_logged_out_temp_buffer, app->register_password_2_logged_out_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedOutRegisterPassword2Input);
         break;
     case 3: // Register button
@@ -1490,9 +1139,13 @@ static void flip_social_logged_in_wifi_settings_ssid_updated(void *context)
         FURI_LOG_E(TAG, "FlipSocialApp is NULL");
         return;
     }
-    // Store the entered name
+    // Store the entered SSID
     strncpy(app->wifi_ssid_logged_in, app->wifi_ssid_logged_in_temp_buffer, app->wifi_ssid_logged_in_temp_buffer_size);
 
+    // Store the entered SSID in the logged out SSID
+    strncpy(app->wifi_ssid_logged_out, app->wifi_ssid_logged_in, app->wifi_ssid_logged_in_temp_buffer_size);
+    strncpy(app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_in, app->wifi_ssid_logged_in_temp_buffer_size);
+
     // Ensure null-termination
     app->wifi_ssid_logged_in[app->wifi_ssid_logged_in_temp_buffer_size - 1] = '\0';
 
@@ -1502,16 +1155,19 @@ static void flip_social_logged_in_wifi_settings_ssid_updated(void *context)
         variable_item_set_current_value_text(app->variable_item_logged_in_wifi_settings_ssid, app->wifi_ssid_logged_in);
     }
 
+    // Save the settings
+    save_settings(app_instance->wifi_ssid_logged_in, app_instance->wifi_password_logged_in, 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);
+
     // update the wifi settings
-    if (!flipper_http_save_wifi(app->wifi_ssid_logged_in, app->wifi_password_logged_in))
+    if (strlen(app->wifi_ssid_logged_in) > 0 && strlen(app->wifi_password_logged_in) > 0)
     {
-        FURI_LOG_E(TAG, "Failed to save wifi settings via UART");
-        FURI_LOG_E(TAG, "Make sure the Flipper is connected to the Wifi Dev Board");
+        if (!flipper_http_save_wifi(app->wifi_ssid_logged_in, app->wifi_password_logged_in))
+        {
+            FURI_LOG_E(TAG, "Failed to save wifi settings via UART");
+            FURI_LOG_E(TAG, "Make sure the Flipper is connected to the Wifi Dev Board");
+        }
     }
 
-    // Save the settings
-    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);
-
     view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedInSettingsWifi);
 }
 
@@ -1531,25 +1187,33 @@ static void flip_social_logged_in_wifi_settings_password_updated(void *context)
     // Store the entered password
     strncpy(app->wifi_password_logged_in, app->wifi_password_logged_in_temp_buffer, app->wifi_password_logged_in_temp_buffer_size);
 
+    // Store the entered password in the logged out password
+    strncpy(app->login_password_logged_out, app->wifi_password_logged_in, app->wifi_password_logged_in_temp_buffer_size);
+    strncpy(app->login_password_logged_out_temp_buffer, app->wifi_password_logged_in, app->wifi_password_logged_in_temp_buffer_size);
+
     // Ensure null-termination
     app->wifi_password_logged_in[app->wifi_password_logged_in_temp_buffer_size - 1] = '\0';
 
     // Update the password item text
     if (app->variable_item_logged_in_wifi_settings_password)
     {
-        variable_item_set_current_value_text(app->variable_item_logged_in_wifi_settings_password, app->wifi_password_logged_in);
+        // dont show the password on the screen (version 0.2)
+        // variable_item_set_current_value_text(app->variable_item_logged_in_wifi_settings_password, app->wifi_password_logged_in);
     }
 
+    // Save the settings
+    save_settings(app_instance->wifi_ssid_logged_in, app_instance->wifi_password_logged_in, 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);
+
     // update the wifi settings
-    if (!flipper_http_save_wifi(app->wifi_ssid_logged_in, app->wifi_password_logged_in))
+    if (strlen(app->wifi_ssid_logged_in) > 0 && strlen(app->wifi_password_logged_in) > 0)
     {
-        FURI_LOG_E(TAG, "Failed to save wifi settings via UART");
-        FURI_LOG_E(TAG, "Make sure the Flipper is connected to the Wifi Dev Board");
+        if (!flipper_http_save_wifi(app->wifi_ssid_logged_in, app->wifi_password_logged_in))
+        {
+            FURI_LOG_E(TAG, "Failed to save wifi settings via UART");
+            FURI_LOG_E(TAG, "Make sure the Flipper is connected to the Wifi Dev Board");
+        }
     }
 
-    // Save the settings
-    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);
-
     view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedInSettingsWifi);
 }
 
@@ -1570,31 +1234,9 @@ static void flip_social_text_input_logged_in_wifi_settings_item_selected(void *c
     switch (index)
     {
     case 0: // Input SSID
-        // Initialize temp_buffer with the current name
-        if (app->wifi_ssid_logged_in && strlen(app->wifi_ssid_logged_in) > 0)
-        {
-            strncpy(app->wifi_ssid_logged_in_temp_buffer, app->wifi_ssid_logged_in, app->wifi_ssid_logged_in_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->wifi_ssid_logged_in_temp_buffer, "", app->wifi_ssid_logged_in_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_in_wifi_settings_ssid, "Enter SSID");
-        uart_text_input_set_result_callback(app->text_input_logged_in_wifi_settings_ssid, flip_social_logged_in_wifi_settings_ssid_updated, app, app->wifi_ssid_logged_in_temp_buffer, app->wifi_ssid_logged_in_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedInWifiSettingsSSIDInput);
         break;
     case 1: // Input Password
-        // Initialize temp_buffer with the current password
-        if (app->wifi_password_logged_in && strlen(app->wifi_password_logged_in) > 0)
-        {
-            strncpy(app->wifi_password_logged_in_temp_buffer, app->wifi_password_logged_in, app->wifi_password_logged_in_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->wifi_password_logged_in_temp_buffer, "", app->wifi_password_logged_in_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_in_wifi_settings_password, "Enter Password");
-        uart_text_input_set_result_callback(app->text_input_logged_in_wifi_settings_password, flip_social_logged_in_wifi_settings_password_updated, app, app->wifi_password_logged_in_temp_buffer, app->wifi_password_logged_in_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedInWifiSettingsPasswordInput);
         break;
     default:
@@ -1671,6 +1313,7 @@ static void flip_social_logged_in_profile_change_password_updated(void *context)
 
     // store the entered password in the logged out password
     strncpy(app->login_password_logged_out, app->change_password_logged_in, app->login_password_logged_out_temp_buffer_size);
+    strncpy(app->login_password_logged_out_temp_buffer, app->change_password_logged_in, app->login_password_logged_out_temp_buffer_size);
 
     // Ensure null-termination
     app->change_password_logged_in[app->change_password_logged_in_temp_buffer_size - 1] = '\0';
@@ -1678,7 +1321,8 @@ static void flip_social_logged_in_profile_change_password_updated(void *context)
     // Update the message item text
     if (app->variable_item_logged_in_profile_change_password)
     {
-        variable_item_set_current_value_text(app->variable_item_logged_in_profile_change_password, app->change_password_logged_in);
+        // dont show the password on the screen (version 0.2)
+        // variable_item_set_current_value_text(app->variable_item_logged_in_profile_change_password, app->change_password_logged_in);
     }
 
     // send post request to change password
@@ -1718,17 +1362,6 @@ static void flip_social_text_input_logged_in_profile_item_selected(void *context
         // do nothing since username cannot be changed
         break;
     case 1: // Change Password
-        // Initialize temp_buffer with the current password
-        if (app->change_password_logged_in && strlen(app->change_password_logged_in) > 0)
-        {
-            strncpy(app->change_password_logged_in_temp_buffer, app->change_password_logged_in, app->change_password_logged_in_temp_buffer_size - 1);
-        }
-        else
-        {
-            strncpy(app->change_password_logged_in_temp_buffer, "", app->change_password_logged_in_temp_buffer_size - 1);
-        }
-        uart_text_input_set_header_text(app->text_input_logged_in_change_password, "Enter New Password");
-        uart_text_input_set_result_callback(app->text_input_logged_in_change_password, flip_social_logged_in_profile_change_password_updated, app, app->change_password_logged_in_temp_buffer, app->change_password_logged_in_temp_buffer_size, false);
         view_dispatcher_switch_to_view(app->view_dispatcher, FlipSocialViewLoggedInChangePasswordInput);
         break;
     default:

+ 18 - 12
flip_social_e.h

@@ -1,18 +1,7 @@
 // flip_social_e.h
 #ifndef FLIP_SOCIAL_E
 #define FLIP_SOCIAL_E
-#include <furi.h>
-#include <furi_hal.h>
-#include <gui/gui.h>
-#include <gui/icon_i.h>
-#include <gui/view.h>
-#include <gui/view_dispatcher.h>
-#include <gui/modules/submenu.h>
-#include <gui/modules/widget.h>
-#include <gui/modules/text_input.h>
-#include <gui/modules/text_box.h>
-#include <gui/modules/variable_item_list.h>
-#include <malloc.h>
+#include <easy_flipper.h>
 #include <dialogs/dialogs.h>
 #include <storage/storage.h>
 #include <flipper_http.h>
@@ -207,4 +196,21 @@ typedef struct
     uint32_t wifi_password_logged_in_temp_buffer_size; // Size of the wifi_password temporary buffer
 
 } FlipSocialApp;
+
+// include strndup (otherwise NULL pointer dereference)
+char *strndup(const char *s, size_t n)
+{
+    char *result;
+    size_t len = strlen(s);
+
+    if (n < len)
+        len = n;
+
+    result = (char *)malloc(len + 1);
+    if (!result)
+        return NULL;
+
+    result[len] = '\0';
+    return (char *)memcpy(result, s, len);
+}
 #endif

+ 266 - 0
flip_social_feed.h

@@ -0,0 +1,266 @@
+#ifndef FLIP_SOCIAL_FEED_H
+#define FLIP_SOCIAL_FEED_H
+
+static FlipSocialApp *app_instance = NULL;
+
+#define MAX_TOKENS 128 // Adjust based on expected JSON tokens
+
+typedef struct
+{
+    char *usernames[128];
+    char *messages[128];
+    bool is_flipped[128];
+    uint32_t ids[128];
+    size_t count;
+    size_t index;
+} FlipSocialFeed;
+
+#define MAX_FEED_ITEMS 128
+#define MAX_LINE_LENGTH 30
+
+// temporary FlipSocialFeed object
+static FlipSocialFeed flip_social_feed = {
+    .usernames = {"JBlanked", "FlipperKing", "FlipperQueen"},
+    .messages = {"Welcome. This is a temp message. Either the feed didn't load or there was a server error.", "I am the Chosen Flipper.", "No one can flip like me."},
+    .is_flipped = {false, false, true},
+    .ids = {0, 1, 2},
+    .count = 3,
+    .index = 0};
+
+bool flip_social_get_feed()
+{
+    // Get the feed from the server
+    if (app_instance->login_username_logged_out == NULL)
+    {
+        FURI_LOG_E(TAG, "Username is NULL");
+        return false;
+    }
+    char command[256];
+    snprintf(command, 128, "https://www.flipsocial.net/api/feed/20/%s/", app_instance->login_username_logged_out);
+    bool success = flipper_http_get_request_with_headers(command, "{\"Content-Type\":\"application/json\"}");
+    if (!success)
+    {
+        FURI_LOG_E(TAG, "Failed to send HTTP request for feed");
+        return false;
+    }
+    fhttp.state = RECEIVING;
+    return true;
+}
+
+bool flip_social_parse_json_feed()
+{
+    // Parse the JSON feed
+    if (fhttp.received_data != NULL)
+    {
+        jsmn_parser parser;
+        jsmn_init(&parser);
+
+        // Allocate tokens array on the heap
+        jsmntok_t *tokens = malloc(sizeof(jsmntok_t) * MAX_TOKENS);
+        if (tokens == NULL)
+        {
+            FURI_LOG_E(TAG, "Failed to allocate memory for JSON tokens.");
+            return false;
+        }
+
+        int ret = jsmn_parse(&parser, fhttp.received_data, strlen(fhttp.received_data), tokens, MAX_TOKENS);
+
+        if (ret < 0)
+        {
+            // Handle parsing errors
+            FURI_LOG_E(TAG, "Failed to parse JSON: %d", ret);
+            free(tokens);
+            return false;
+        }
+
+        // Ensure that the root element is an object
+        if (ret < 1 || tokens[0].type != JSMN_OBJECT)
+        {
+            FURI_LOG_E(TAG, "Root element is not an object.");
+            free(tokens);
+            return false;
+        }
+
+        // Initialize feed count
+        flip_social_feed.count = 0;
+
+        // Loop over all keys in the root object
+        int i = 0;
+        for (i = 1; i < ret; i++)
+        {
+            if (jsoneq(fhttp.received_data, &tokens[i], "feed") == 0)
+            {
+                // Found "feed" key
+                jsmntok_t *feed_array = &tokens[i + 1];
+
+                if (feed_array->type != JSMN_ARRAY)
+                {
+                    FURI_LOG_E(TAG, "'feed' is not an array.");
+                    break;
+                }
+
+                int j, k;
+                int feed_index = 0;
+
+                // Iterate over the feed array
+                for (j = 0; j < feed_array->size; j++)
+                {
+                    int idx = i + 2; // Position of the first feed item
+                    for (k = 0; k < j; k++)
+                    {
+                        // Skip tokens of previous feed items
+                        idx += tokens[idx].size * 2 + 1;
+                    }
+
+                    if (idx >= ret)
+                    {
+                        FURI_LOG_E(TAG, "Index out of bounds while accessing feed items.");
+                        break;
+                    }
+
+                    jsmntok_t *item = &tokens[idx];
+                    if (item->type != JSMN_OBJECT)
+                    {
+                        FURI_LOG_E(TAG, "Feed item is not an object.");
+                        continue;
+                    }
+
+                    // Variables to hold item data
+                    char *username = NULL;
+                    char *message = NULL;
+                    int flipped = 0;
+                    int id = 0;
+
+                    // Iterate over keys in the feed item
+                    int l;
+                    int item_size = item->size;
+                    int item_idx = idx + 1; // Position of the first key in the item
+
+                    for (l = 0; l < item_size; l++)
+                    {
+                        if (item_idx + 1 >= ret)
+                        {
+                            FURI_LOG_E(TAG, "Index out of bounds while accessing item properties.");
+                            break;
+                        }
+
+                        jsmntok_t *key = &tokens[item_idx];
+                        jsmntok_t *val = &tokens[item_idx + 1];
+
+                        if (jsoneq(fhttp.received_data, key, "username") == 0)
+                        {
+                            username = strndup(fhttp.received_data + val->start, val->end - val->start);
+                        }
+                        else if (jsoneq(fhttp.received_data, key, "message") == 0)
+                        {
+                            message = strndup(fhttp.received_data + val->start, val->end - val->start);
+                        }
+                        else if (jsoneq(fhttp.received_data, key, "flipped") == 0)
+                        {
+                            if (val->type == JSMN_PRIMITIVE)
+                            {
+                                if (strncmp(fhttp.received_data + val->start, "true", val->end - val->start) == 0)
+                                    flipped = 1;
+                                else
+                                    flipped = 0;
+                            }
+                        }
+                        else if (jsoneq(fhttp.received_data, key, "id") == 0)
+                        {
+                            if (val->type == JSMN_PRIMITIVE)
+                            {
+                                char id_str[16] = {0};
+                                uint32_t id_len = val->end - val->start;
+                                if (id_len >= sizeof(id_str))
+                                    id_len = sizeof(id_str) - 1;
+                                strncpy(id_str, fhttp.received_data + val->start, id_len);
+                                id = atoi(id_str);
+                            }
+                        }
+
+                        item_idx += 2; // Move to the next key-value pair
+                    }
+
+                    // Store the data in flip_social_feed
+                    if (username && message && feed_index < MAX_FEED_ITEMS)
+                    {
+                        flip_social_feed.usernames[feed_index] = username;
+                        flip_social_feed.messages[feed_index] = message;
+                        flip_social_feed.is_flipped[feed_index] = flipped;
+                        flip_social_feed.ids[feed_index] = id;
+                        feed_index++;
+                        flip_social_feed.count = feed_index;
+                    }
+                    else
+                    {
+                        // Free allocated memory if not stored
+                        if (username)
+                            free(username);
+                        if (message)
+                            free(message);
+                    }
+                }
+                break; // Feed processed
+            }
+        }
+
+        free(tokens); // Free the allocated tokens array
+    }
+    else
+    {
+        FURI_LOG_E(TAG, "No data received.");
+        return false;
+    }
+
+    return true;
+}
+
+bool flip_social_board_is_active(Canvas *canvas)
+{
+    if (fhttp.state == INACTIVE)
+    {
+        canvas_draw_str(canvas, 0, 7, "Wifi Dev Board disconnected.");
+        canvas_draw_str(canvas, 0, 17, "Please connect to the board.");
+        canvas_draw_str(canvas, 0, 32, "If your board is connected,");
+        canvas_draw_str(canvas, 0, 42, "make sure you have flashed");
+        canvas_draw_str(canvas, 0, 52, "your WiFi Devboard with the");
+        canvas_draw_str(canvas, 0, 62, "latest FlipperHTTP flash.");
+        return false;
+    }
+    return true;
+}
+
+void flip_social_handle_error(Canvas *canvas)
+{
+    if (fhttp.received_data != NULL)
+    {
+        if (strstr(fhttp.received_data, "[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.received_data, "[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.");
+    }
+}
+
+#endif // FLIP_SOCIAL_FEED_H

+ 311 - 252
flip_social_i.h

@@ -11,22 +11,9 @@ static FlipSocialApp *flip_social_app_alloc()
 {
     // Initiailize the app
     FlipSocialApp *app = (FlipSocialApp *)malloc(sizeof(FlipSocialApp));
-    if (!app)
-    {
-        // Allocation failed
-        FURI_LOG_E(TAG, "Failed to allocate FlipSocialApp");
-        return NULL;
-    }
-    memset(app, 0, sizeof(FlipSocialApp));
 
     // Initialize gui
     Gui *gui = furi_record_open(RECORD_GUI);
-    if (!gui)
-    {
-        // Failed to open GUI
-        FURI_LOG_E(TAG, "Failed to open GUI record");
-        return NULL;
-    }
 
     // Initialize UART
     if (!flipper_http_init(flipper_http_rx_callback, app))
@@ -36,160 +23,196 @@ static FlipSocialApp *flip_social_app_alloc()
     }
 
     // Allocate ViewDispatcher
-    app->view_dispatcher = view_dispatcher_alloc();
-    if (!app->view_dispatcher)
+    if (!easy_flipper_set_view_dispatcher(&app->view_dispatcher, gui, app))
     {
-        FURI_LOG_E(TAG, "Failed to allocate ViewDispatcher");
         return NULL;
     }
-    // Attach ViewDispatcher to GUI
-    view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
-    view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
-
-    // initialize members
-    app->wifi_ssid_logged_out_temp_buffer_size = 128;
-    app->wifi_password_logged_out_temp_buffer_size = 128;
-    app->wifi_ssid_logged_out_temp_buffer = (char *)malloc(app->wifi_ssid_logged_out_temp_buffer_size);
-    app->wifi_password_logged_out_temp_buffer = (char *)malloc(app->wifi_password_logged_out_temp_buffer_size);
-    app->wifi_ssid_logged_out = (char *)malloc(app->wifi_ssid_logged_out_temp_buffer_size);
-    app->wifi_password_logged_out = (char *)malloc(app->wifi_password_logged_out_temp_buffer_size);
-
-    app->login_username_logged_out_temp_buffer_size = 128;
-    app->login_password_logged_out_temp_buffer_size = 128;
-    app->login_username_logged_out_temp_buffer = (char *)malloc(app->login_username_logged_out_temp_buffer_size);
-    app->login_password_logged_out_temp_buffer = (char *)malloc(app->login_password_logged_out_temp_buffer_size);
-    app->login_username_logged_out = (char *)malloc(app->login_username_logged_out_temp_buffer_size);
-    app->login_password_logged_out = (char *)malloc(app->login_password_logged_out_temp_buffer_size);
-
-    app->register_username_logged_out_temp_buffer_size = 128;
-    app->register_password_logged_out_temp_buffer_size = 128;
-    app->register_password_2_logged_out_temp_buffer_size = 128;
-    app->register_username_logged_out_temp_buffer = (char *)malloc(app->register_username_logged_out_temp_buffer_size);
-    app->register_password_logged_out_temp_buffer = (char *)malloc(app->register_password_logged_out_temp_buffer_size);
-    app->register_password_2_logged_out_temp_buffer = (char *)malloc(app->register_password_2_logged_out_temp_buffer_size);
-    app->register_username_logged_out = (char *)malloc(app->register_username_logged_out_temp_buffer_size);
-    app->register_password_logged_out = (char *)malloc(app->register_password_logged_out_temp_buffer_size);
-    app->register_password_2_logged_out = (char *)malloc(app->register_password_2_logged_out_temp_buffer_size);
-
-    app->change_password_logged_in_temp_buffer_size = 128;
-    app->compose_pre_save_logged_in_temp_buffer_size = 128;
-    app->wifi_ssid_logged_in_temp_buffer_size = 128;
-    app->wifi_password_logged_in_temp_buffer_size = 128;
-    app->is_logged_in_size = 128;
-    app->login_username_logged_in_temp_buffer_size = 128;
-
-    app->change_password_logged_in_temp_buffer = (char *)malloc(app->change_password_logged_in_temp_buffer_size);
-    app->compose_pre_save_logged_in_temp_buffer = (char *)malloc(app->compose_pre_save_logged_in_temp_buffer_size);
-    app->wifi_ssid_logged_in_temp_buffer = (char *)malloc(app->wifi_ssid_logged_in_temp_buffer_size);
-    app->wifi_password_logged_in_temp_buffer = (char *)malloc(app->wifi_password_logged_in_temp_buffer_size);
-    app->change_password_logged_in = (char *)malloc(app->change_password_logged_in_temp_buffer_size);
-    app->compose_pre_save_logged_in = (char *)malloc(app->compose_pre_save_logged_in_temp_buffer_size);
-    app->wifi_ssid_logged_in = (char *)malloc(app->wifi_ssid_logged_in_temp_buffer_size);
-    app->wifi_password_logged_in = (char *)malloc(app->wifi_password_logged_in_temp_buffer_size);
-    app->is_logged_in = (char *)malloc(app->is_logged_in_size);
-    app->login_username_logged_in = (char *)malloc(app->login_username_logged_in_temp_buffer_size);
-
-    if (!app->wifi_ssid_logged_out || !app->wifi_password_logged_out ||
-        !app->login_username_logged_out || !app->login_password_logged_out ||
-        !app->register_username_logged_out || !app->register_password_logged_out ||
-        !app->register_password_2_logged_out || !app->change_password_logged_in || !app->compose_pre_save_logged_in || !app->wifi_ssid_logged_in || !app->wifi_password_logged_in ||
-        !app->change_password_logged_in || !app->compose_pre_save_logged_in || !app->wifi_ssid_logged_in || !app->wifi_password_logged_in ||
-        !app->is_logged_in || !app->login_username_logged_in)
 
+    // Allocate the text input buffers
+    app->wifi_ssid_logged_out_temp_buffer_size = 64;
+    app->wifi_password_logged_out_temp_buffer_size = 64;
+    app->login_username_logged_out_temp_buffer_size = 64;
+    app->login_password_logged_out_temp_buffer_size = 64;
+    app->register_username_logged_out_temp_buffer_size = 64;
+    app->register_password_logged_out_temp_buffer_size = 64;
+    app->register_password_2_logged_out_temp_buffer_size = 64;
+    app->change_password_logged_in_temp_buffer_size = 64;
+    app->compose_pre_save_logged_in_temp_buffer_size = 64;
+    app->wifi_ssid_logged_in_temp_buffer_size = 64;
+    app->wifi_password_logged_in_temp_buffer_size = 64;
+    app->is_logged_in_size = 8;
+    app->login_username_logged_in_temp_buffer_size = 64;
+
+    if (!easy_flipper_set_buffer(&app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->wifi_password_logged_out_temp_buffer, app->wifi_password_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->login_username_logged_out_temp_buffer, app->login_username_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->login_password_logged_out_temp_buffer, app->login_password_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->register_username_logged_out_temp_buffer, app->register_username_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->register_password_logged_out_temp_buffer, app->register_password_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->register_password_2_logged_out_temp_buffer, app->register_password_2_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->change_password_logged_in_temp_buffer, app->change_password_logged_in_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->compose_pre_save_logged_in_temp_buffer, app->compose_pre_save_logged_in_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->wifi_ssid_logged_in_temp_buffer, app->wifi_ssid_logged_in_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->wifi_password_logged_in_temp_buffer, app->wifi_password_logged_in_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->is_logged_in, app->is_logged_in_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->login_username_logged_in_temp_buffer, app->login_username_logged_in_temp_buffer_size))
     {
-        // Allocation failed
-        FURI_LOG_E(TAG, "Failed to allocate buffers");
         return NULL;
     }
 
-    // Initialize buffers with empty strings
-    app->wifi_ssid_logged_out_temp_buffer[0] = '\0';
-    app->wifi_password_logged_out_temp_buffer[0] = '\0';
-    app->login_username_logged_out_temp_buffer[0] = '\0';
-    app->login_password_logged_out_temp_buffer[0] = '\0';
-    app->register_username_logged_out_temp_buffer[0] = '\0';
-    app->register_password_logged_out_temp_buffer[0] = '\0';
-    app->register_password_2_logged_out_temp_buffer[0] = '\0';
-    app->change_password_logged_in_temp_buffer[0] = '\0';
-    app->compose_pre_save_logged_in_temp_buffer[0] = '\0';
-    app->wifi_ssid_logged_in_temp_buffer[0] = '\0';
-    app->wifi_password_logged_in_temp_buffer[0] = '\0';
-    app->change_password_logged_in[0] = '\0';
-    app->compose_pre_save_logged_in[0] = '\0';
-    app->wifi_ssid_logged_in[0] = '\0';
-    app->wifi_password_logged_in[0] = '\0';
-    app->is_logged_in[0] = '\0';
-    app->login_username_logged_in[0] = '\0';
+    if (!easy_flipper_set_buffer(&app->wifi_ssid_logged_out, app->wifi_ssid_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->wifi_password_logged_out, app->wifi_password_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->login_username_logged_out, app->login_username_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->login_password_logged_out, app->login_password_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->register_username_logged_out, app->register_username_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->register_password_logged_out, app->register_password_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->register_password_2_logged_out, app->register_password_2_logged_out_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->change_password_logged_in, app->change_password_logged_in_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->compose_pre_save_logged_in, app->compose_pre_save_logged_in_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->wifi_ssid_logged_in, app->wifi_ssid_logged_in_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->wifi_password_logged_in, app->wifi_password_logged_in_temp_buffer_size))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_buffer(&app->login_username_logged_in, app->login_username_logged_in_temp_buffer_size))
+    {
+        return NULL;
+    }
 
-    // Setup Submenu(s)
-    app->submenu_logged_out = submenu_alloc();
-    app->submenu_logged_in = submenu_alloc();
-    app->submenu_compose = submenu_alloc();
-    if (!app->submenu_logged_out || !app->submenu_logged_in || !app->submenu_compose)
+    // Allocate Submenu(s)
+    if (!easy_flipper_set_submenu(&app->submenu_logged_out, FlipSocialViewLoggedOutSubmenu, "FlipSocial v0.2", flip_social_callback_exit_app, &app->view_dispatcher))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_submenu(&app->submenu_logged_in, FlipSocialViewLoggedInSubmenu, "FlipSocial v0.2", 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))
     {
-        FURI_LOG_E(TAG, "Failed to allocate Submenus");
         return NULL;
     }
-    submenu_set_header(app->submenu_logged_out, "FlipSocial");
-    submenu_set_header(app->submenu_logged_in, "FlipSocial");
-    submenu_set_header(app->submenu_compose, "Create A Post");
+
     submenu_add_item(app->submenu_logged_out, "Login", FlipSocialSubmenuLoggedOutIndexLogin, flip_social_callback_submenu_choices, app);
     submenu_add_item(app->submenu_logged_out, "Register", FlipSocialSubmenuLoggedOutIndexRegister, flip_social_callback_submenu_choices, app);
     submenu_add_item(app->submenu_logged_out, "About", FlipSocialSubmenuLoggedOutIndexAbout, flip_social_callback_submenu_choices, app);
     submenu_add_item(app->submenu_logged_out, "Settings", FlipSocialSubmenuLoggedOutIndexWifiSettings, flip_social_callback_submenu_choices, app);
+    //
     submenu_add_item(app->submenu_logged_in, "Feed", FlipSocialSubmenuLoggedInIndexFeed, flip_social_callback_submenu_choices, app);
     submenu_add_item(app->submenu_logged_in, "Post", FlipSocialSubmenuLoggedInIndexCompose, flip_social_callback_submenu_choices, app);
     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);
 
-    view_set_previous_callback(submenu_get_view(app->submenu_logged_out), flip_social_callback_exit_app);
-    view_set_previous_callback(submenu_get_view(app->submenu_logged_in), flip_social_callback_exit_app); // exit the app isntead of returning to the logged out screen
-    view_set_previous_callback(submenu_get_view(app->submenu_compose), flip_social_callback_to_submenu_logged_in);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutSubmenu, submenu_get_view(app->submenu_logged_out));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInSubmenu, submenu_get_view(app->submenu_logged_in));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInCompose, submenu_get_view(app->submenu_compose));
-
-    app->view_process_login = view_alloc();
-    app->view_process_register = view_alloc();
-    app->view_process_feed = view_alloc();
-    app->view_process_compose = view_alloc();
-    if (!app->view_process_login || !app->view_process_register || !app->view_process_feed || !app->view_process_compose)
-    {
-        FURI_LOG_E(TAG, "Failed to allocate View");
-        return NULL;
-    }
-    view_set_draw_callback(app->view_process_login, flip_social_callback_draw_login);
-    view_set_draw_callback(app->view_process_register, flip_social_callback_draw_register);
-    view_set_draw_callback(app->view_process_feed, flip_social_callback_draw_feed);
-    view_set_draw_callback(app->view_process_compose, flip_social_callback_draw_compose);
-    view_set_context(app->view_process_login, app);
-    view_set_context(app->view_process_register, app);
-    view_set_context(app->view_process_feed, app);
-    view_set_context(app->view_process_compose, app);
-    view_set_previous_callback(app->view_process_login, flip_social_callback_to_login_logged_out);
-    view_set_previous_callback(app->view_process_register, flip_social_callback_to_register_logged_out);
-    view_set_previous_callback(app->view_process_feed, flip_social_callback_to_submenu_logged_in);
-    view_set_previous_callback(app->view_process_compose, flip_social_callback_to_compose_logged_in);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutProcessLogin, app->view_process_login);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutProcessRegister, app->view_process_register);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInFeed, app->view_process_feed);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInProcessCompose, app->view_process_compose);
+    // 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;
+    }
 
     // Setup Variable Item List(s)
-    app->variable_item_list_logged_out_wifi_settings = variable_item_list_alloc();
-    app->variable_item_list_logged_out_login = variable_item_list_alloc();
-    app->variable_item_list_logged_out_register = variable_item_list_alloc();
-    app->variable_item_list_logged_in_profile = variable_item_list_alloc();
-    app->variable_item_list_logged_in_settings = variable_item_list_alloc();
-    app->variable_item_list_logged_in_settings_wifi = variable_item_list_alloc();
-    if (!app->variable_item_list_logged_out_wifi_settings || !app->variable_item_list_logged_out_login ||
-        !app->variable_item_list_logged_out_register || !app->variable_item_list_logged_in_profile ||
-        !app->variable_item_list_logged_in_settings || !app->variable_item_list_logged_in_settings_wifi)
+    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))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_variable_item_list(&app->variable_item_list_logged_out_login, FlipSocialViewLoggedOutLogin, flip_social_text_input_logged_out_login_item_selected, flip_social_callback_to_submenu_logged_out, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_variable_item_list(&app->variable_item_list_logged_out_register, FlipSocialViewLoggedOutRegister, flip_social_text_input_logged_out_register_item_selected, flip_social_callback_to_submenu_logged_out, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_variable_item_list(&app->variable_item_list_logged_in_profile, FlipSocialViewLoggedInProfile, flip_social_text_input_logged_in_profile_item_selected, flip_social_callback_to_submenu_logged_in, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_variable_item_list(&app->variable_item_list_logged_in_settings, FlipSocialViewLoggedInSettings, flip_social_text_input_logged_in_settings_item_selected, flip_social_callback_to_submenu_logged_in, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_variable_item_list(&app->variable_item_list_logged_in_settings_wifi, FlipSocialViewLoggedInSettingsWifi, flip_social_text_input_logged_in_wifi_settings_item_selected, flip_social_callback_to_settings_logged_in, &app->view_dispatcher, app))
     {
-        FURI_LOG_E(TAG, "Failed to allocate VariableItemList");
         return NULL;
     }
 
@@ -214,103 +237,62 @@ static FlipSocialApp *flip_social_app_alloc()
     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);
 
-    variable_item_list_set_enter_callback(app->variable_item_list_logged_out_wifi_settings, flip_social_text_input_logged_out_wifi_settings_item_selected, app);
-    view_set_previous_callback(variable_item_list_get_view(app->variable_item_list_logged_out_wifi_settings), flip_social_callback_to_submenu_logged_out);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutWifiSettings, variable_item_list_get_view(app->variable_item_list_logged_out_wifi_settings));
-    //
-    variable_item_list_set_enter_callback(app->variable_item_list_logged_out_login, flip_social_text_input_logged_out_login_item_selected, app);
-    view_set_previous_callback(variable_item_list_get_view(app->variable_item_list_logged_out_login), flip_social_callback_to_submenu_logged_out);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutLogin, variable_item_list_get_view(app->variable_item_list_logged_out_login));
-    //
-    variable_item_list_set_enter_callback(app->variable_item_list_logged_out_register, flip_social_text_input_logged_out_register_item_selected, app);
-    view_set_previous_callback(variable_item_list_get_view(app->variable_item_list_logged_out_register), flip_social_callback_to_submenu_logged_out);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutRegister, variable_item_list_get_view(app->variable_item_list_logged_out_register));
-    //
-    variable_item_list_set_enter_callback(app->variable_item_list_logged_in_profile, flip_social_text_input_logged_in_profile_item_selected, app);
-    view_set_previous_callback(variable_item_list_get_view(app->variable_item_list_logged_in_profile), flip_social_callback_to_submenu_logged_in);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInProfile, variable_item_list_get_view(app->variable_item_list_logged_in_profile));
-    //
-    variable_item_list_set_enter_callback(app->variable_item_list_logged_in_settings, flip_social_text_input_logged_in_settings_item_selected, app);
-    view_set_previous_callback(variable_item_list_get_view(app->variable_item_list_logged_in_settings), flip_social_callback_to_submenu_logged_in);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInSettings, variable_item_list_get_view(app->variable_item_list_logged_in_settings));
-    //
-    variable_item_list_set_enter_callback(app->variable_item_list_logged_in_settings_wifi, flip_social_text_input_logged_in_wifi_settings_item_selected, app);
-    view_set_previous_callback(variable_item_list_get_view(app->variable_item_list_logged_in_settings_wifi), flip_social_callback_to_settings_logged_in);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInSettingsWifi, variable_item_list_get_view(app->variable_item_list_logged_in_settings_wifi));
-
     // Setup Text Input(s)
-    app->text_input_logged_out_wifi_settings_ssid = uart_text_input_alloc();
-    app->text_input_logged_out_wifi_settings_password = uart_text_input_alloc();
-    app->text_input_logged_out_login_username = uart_text_input_alloc();
-    app->text_input_logged_out_login_password = uart_text_input_alloc();
-    app->text_input_logged_out_register_username = uart_text_input_alloc();
-    app->text_input_logged_out_register_password = uart_text_input_alloc();
-    app->text_input_logged_out_register_password_2 = uart_text_input_alloc();
-    app->text_input_logged_in_change_password = uart_text_input_alloc();
-    app->text_input_logged_in_compose_pre_save_input = uart_text_input_alloc();
-    app->text_input_logged_in_wifi_settings_ssid = uart_text_input_alloc();
-    app->text_input_logged_in_wifi_settings_password = uart_text_input_alloc();
-    if (!app->text_input_logged_out_wifi_settings_ssid || !app->text_input_logged_out_wifi_settings_password || !app->text_input_logged_out_login_username ||
-        !app->text_input_logged_out_login_password || !app->text_input_logged_out_register_username || !app->text_input_logged_out_register_password ||
-        !app->text_input_logged_out_register_password_2 || !app->text_input_logged_in_change_password ||
-        !app->text_input_logged_in_compose_pre_save_input || !app->text_input_logged_in_wifi_settings_ssid ||
-        !app->text_input_logged_in_wifi_settings_password)
-    {
-        FURI_LOG_E(TAG, "Failed to allocate Text Input");
-        return NULL;
-    }
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutWifiSettingsSSIDInput, uart_text_input_get_view(app->text_input_logged_out_wifi_settings_ssid));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutWifiSettingsPasswordInput, uart_text_input_get_view(app->text_input_logged_out_wifi_settings_password));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutLoginUsernameInput, uart_text_input_get_view(app->text_input_logged_out_login_username));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutLoginPasswordInput, uart_text_input_get_view(app->text_input_logged_out_login_password));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutRegisterUsernameInput, uart_text_input_get_view(app->text_input_logged_out_register_username));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutRegisterPasswordInput, uart_text_input_get_view(app->text_input_logged_out_register_password));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutRegisterPassword2Input, uart_text_input_get_view(app->text_input_logged_out_register_password_2));
-    //
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInChangePasswordInput, uart_text_input_get_view(app->text_input_logged_in_change_password));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInComposeAddPreSaveInput, uart_text_input_get_view(app->text_input_logged_in_compose_pre_save_input));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInWifiSettingsSSIDInput, uart_text_input_get_view(app->text_input_logged_in_wifi_settings_ssid));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInWifiSettingsPasswordInput, uart_text_input_get_view(app->text_input_logged_in_wifi_settings_password));
-
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_out_wifi_settings_ssid), flip_social_callback_to_wifi_settings_logged_out);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_out_wifi_settings_password), flip_social_callback_to_wifi_settings_logged_out);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_out_login_username), flip_social_callback_to_login_logged_out);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_out_login_password), flip_social_callback_to_login_logged_out);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_out_register_username), flip_social_callback_to_register_logged_out);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_out_register_password), flip_social_callback_to_register_logged_out);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_out_register_password_2), flip_social_callback_to_register_logged_out);
+    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))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_out_wifi_settings_password, FlipSocialViewLoggedOutWifiSettingsPasswordInput, "Enter Password", app->wifi_password_logged_out_temp_buffer, app->wifi_password_logged_out_temp_buffer_size, flip_social_logged_out_wifi_settings_password_updated, flip_social_callback_to_wifi_settings_logged_out, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_out_login_username, FlipSocialViewLoggedOutLoginUsernameInput, "Enter Username", app->login_username_logged_out_temp_buffer, app->login_username_logged_out_temp_buffer_size, flip_social_logged_out_login_username_updated, flip_social_callback_to_login_logged_out, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_out_login_password, FlipSocialViewLoggedOutLoginPasswordInput, "Enter Password", app->login_password_logged_out_temp_buffer, app->login_password_logged_out_temp_buffer_size, flip_social_logged_out_login_password_updated, flip_social_callback_to_login_logged_out, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_out_register_username, FlipSocialViewLoggedOutRegisterUsernameInput, "Enter Username", app->register_username_logged_out_temp_buffer, app->register_username_logged_out_temp_buffer_size, flip_social_logged_out_register_username_updated, flip_social_callback_to_register_logged_out, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_out_register_password, FlipSocialViewLoggedOutRegisterPasswordInput, "Enter Password", app->register_password_logged_out_temp_buffer, app->register_password_logged_out_temp_buffer_size, flip_social_logged_out_register_password_updated, flip_social_callback_to_register_logged_out, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_out_register_password_2, FlipSocialViewLoggedOutRegisterPassword2Input, "Confirm Password", app->register_password_2_logged_out_temp_buffer, app->register_password_2_logged_out_temp_buffer_size, flip_social_logged_out_register_password_2_updated, flip_social_callback_to_register_logged_out, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
     //
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_in_change_password), flip_social_callback_to_profile_logged_in);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_in_compose_pre_save_input), flip_social_callback_to_compose_logged_in);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_in_wifi_settings_ssid), flip_social_callback_to_wifi_settings_logged_in);
-    view_set_previous_callback(uart_text_input_get_view(app->text_input_logged_in_wifi_settings_password), flip_social_callback_to_wifi_settings_logged_in);
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_in_change_password, FlipSocialViewLoggedInChangePasswordInput, "Enter New Password", app->change_password_logged_in_temp_buffer, app->change_password_logged_in_temp_buffer_size, flip_social_logged_in_profile_change_password_updated, flip_social_callback_to_profile_logged_in, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_in_compose_pre_save_input, FlipSocialViewLoggedInComposeAddPreSaveInput, "Enter Pre-Save Message", app->compose_pre_save_logged_in_temp_buffer, app->compose_pre_save_logged_in_temp_buffer_size, flip_social_logged_in_compose_pre_save_updated, flip_social_callback_to_compose_logged_in, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_in_wifi_settings_ssid, FlipSocialViewLoggedInWifiSettingsSSIDInput, "Enter SSID", app->wifi_ssid_logged_in_temp_buffer, app->wifi_ssid_logged_in_temp_buffer_size, flip_social_logged_in_wifi_settings_ssid_updated, flip_social_callback_to_wifi_settings_logged_in, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
+    if (!easy_flipper_set_uart_text_input(&app->text_input_logged_in_wifi_settings_password, FlipSocialViewLoggedInWifiSettingsPasswordInput, "Enter Password", app->wifi_password_logged_in_temp_buffer, app->wifi_password_logged_in_temp_buffer_size, flip_social_logged_in_wifi_settings_password_updated, flip_social_callback_to_wifi_settings_logged_in, &app->view_dispatcher, app))
+    {
+        return NULL;
+    }
 
     // Setup About(s)
-    app->widget_logged_out_about = widget_alloc();
-    app->widget_logged_in_about = widget_alloc();
-    if (!app->widget_logged_out_about || !app->widget_logged_in_about)
-    {
-        FURI_LOG_E(TAG, "Failed to allocate Widget");
-        return NULL;
-    }
-    widget_add_text_scroll_element(
-        app->widget_logged_out_about,
-        0,
-        0,
-        128,
-        64,
-        "Welcome to FlipSocial\n---\nThe social media app for\nFlipper Zero, created by\nJBlanked.\n---\nPress BACK to return.");
-    widget_add_text_scroll_element(
-        app->widget_logged_in_about,
-        0,
-        0,
-        128,
-        64,
-        "Welcome to FlipSocial\n---\nThe social media app for\nFlipper Zero, created by\nJBlanked.\n---\nPress BACK to return.");
-    view_set_previous_callback(widget_get_view(app->widget_logged_in_about), flip_social_callback_to_settings_logged_in);
-    view_set_previous_callback(widget_get_view(app->widget_logged_out_about), flip_social_callback_to_submenu_logged_out);
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedInSettingsAbout, widget_get_view(app->widget_logged_in_about));
-    view_dispatcher_add_view(app->view_dispatcher, FlipSocialViewLoggedOutAbout, widget_get_view(app->widget_logged_out_about));
+    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.\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.\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))
@@ -350,28 +332,16 @@ static FlipSocialApp *flip_social_app_alloc()
     }
     else
     {
-        // set variable item text
-        // Update variable items
-        variable_item_set_current_value_text(app->variable_item_logged_in_wifi_settings_ssid, app->wifi_ssid_logged_in);
-        variable_item_set_current_value_text(app->variable_item_logged_in_wifi_settings_password, app->wifi_password_logged_in);
-        variable_item_set_current_value_text(app->variable_item_logged_out_wifi_settings_ssid, app->wifi_ssid_logged_out);
-        variable_item_set_current_value_text(app->variable_item_logged_out_wifi_settings_password, app->wifi_password_logged_out);
-
-        variable_item_set_current_value_text(app->variable_item_logged_out_login_username, app->login_username_logged_out);
-        variable_item_set_current_value_text(app->variable_item_logged_out_login_password, app->login_password_logged_out);
-        variable_item_set_current_value_text(app->variable_item_logged_in_profile_username, app->login_username_logged_in);
-        variable_item_set_current_value_text(app->variable_item_logged_in_profile_change_password, app->change_password_logged_in);
-
         // Copy items into their temp buffers with safety checks
-        if (app->wifi_ssid_logged_in && app->wifi_ssid_logged_in_temp_buffer)
+        if (app->wifi_ssid_logged_out && app->wifi_ssid_logged_out_temp_buffer)
         {
-            strncpy(app->wifi_ssid_logged_in_temp_buffer, app->wifi_ssid_logged_in, app->wifi_ssid_logged_in_temp_buffer_size - 1);
-            app->wifi_ssid_logged_in_temp_buffer[app->wifi_ssid_logged_in_temp_buffer_size - 1] = '\0';
+            strncpy(app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_out, app->wifi_ssid_logged_out_temp_buffer_size - 1);
+            app->wifi_ssid_logged_out_temp_buffer[app->wifi_ssid_logged_out_temp_buffer_size - 1] = '\0';
         }
-        if (app->wifi_password_logged_in && app->wifi_password_logged_in_temp_buffer)
+        if (app->wifi_password_logged_out && app->wifi_password_logged_out_temp_buffer)
         {
-            strncpy(app->wifi_password_logged_in_temp_buffer, app->wifi_password_logged_in, app->wifi_password_logged_in_temp_buffer_size - 1);
-            app->wifi_password_logged_in_temp_buffer[app->wifi_password_logged_in_temp_buffer_size - 1] = '\0';
+            strncpy(app->wifi_password_logged_out_temp_buffer, app->wifi_password_logged_out, app->wifi_password_logged_out_temp_buffer_size - 1);
+            app->wifi_password_logged_out_temp_buffer[app->wifi_password_logged_out_temp_buffer_size - 1] = '\0';
         }
         if (app->login_username_logged_out && app->login_username_logged_out_temp_buffer)
         {
@@ -383,11 +353,41 @@ static FlipSocialApp *flip_social_app_alloc()
             strncpy(app->login_password_logged_out_temp_buffer, app->login_password_logged_out, app->login_password_logged_out_temp_buffer_size - 1);
             app->login_password_logged_out_temp_buffer[app->login_password_logged_out_temp_buffer_size - 1] = '\0';
         }
+        if (app->register_username_logged_out && app->register_username_logged_out_temp_buffer)
+        {
+            strncpy(app->register_username_logged_out_temp_buffer, app->register_username_logged_out, app->register_username_logged_out_temp_buffer_size - 1);
+            app->register_username_logged_out_temp_buffer[app->register_username_logged_out_temp_buffer_size - 1] = '\0';
+        }
+        if (app->register_password_logged_out && app->register_password_logged_out_temp_buffer)
+        {
+            strncpy(app->register_password_logged_out_temp_buffer, app->register_password_logged_out, app->register_password_logged_out_temp_buffer_size - 1);
+            app->register_password_logged_out_temp_buffer[app->register_password_logged_out_temp_buffer_size - 1] = '\0';
+        }
+        if (app->register_password_2_logged_out && app->register_password_2_logged_out_temp_buffer)
+        {
+            strncpy(app->register_password_2_logged_out_temp_buffer, app->register_password_2_logged_out, app->register_password_2_logged_out_temp_buffer_size - 1);
+            app->register_password_2_logged_out_temp_buffer[app->register_password_2_logged_out_temp_buffer_size - 1] = '\0';
+        }
         if (app->change_password_logged_in && app->change_password_logged_in_temp_buffer)
         {
             strncpy(app->change_password_logged_in_temp_buffer, app->change_password_logged_in, app->change_password_logged_in_temp_buffer_size - 1);
             app->change_password_logged_in_temp_buffer[app->change_password_logged_in_temp_buffer_size - 1] = '\0';
         }
+        if (app->compose_pre_save_logged_in && app->compose_pre_save_logged_in_temp_buffer)
+        {
+            strncpy(app->compose_pre_save_logged_in_temp_buffer, app->compose_pre_save_logged_in, app->compose_pre_save_logged_in_temp_buffer_size - 1);
+            app->compose_pre_save_logged_in_temp_buffer[app->compose_pre_save_logged_in_temp_buffer_size - 1] = '\0';
+        }
+        if (app->wifi_ssid_logged_in && app->wifi_ssid_logged_in_temp_buffer)
+        {
+            strncpy(app->wifi_ssid_logged_in_temp_buffer, app->wifi_ssid_logged_in, app->wifi_ssid_logged_in_temp_buffer_size - 1);
+            app->wifi_ssid_logged_in_temp_buffer[app->wifi_ssid_logged_in_temp_buffer_size - 1] = '\0';
+        }
+        if (app->wifi_password_logged_in && app->wifi_password_logged_in_temp_buffer)
+        {
+            strncpy(app->wifi_password_logged_in_temp_buffer, app->wifi_password_logged_in, app->wifi_password_logged_in_temp_buffer_size - 1);
+            app->wifi_password_logged_in_temp_buffer[app->wifi_password_logged_in_temp_buffer_size - 1] = '\0';
+        }
         if (app->login_username_logged_in && app->login_username_logged_in_temp_buffer)
         {
             strncpy(app->login_username_logged_in_temp_buffer, app->login_username_logged_in, app->login_username_logged_in_temp_buffer_size - 1);
@@ -398,14 +398,73 @@ static FlipSocialApp *flip_social_app_alloc()
         if (strlen(app->login_username_logged_out) > 0 && strlen(app->login_username_logged_in) == 0)
         {
             strncpy(app->login_username_logged_in, app->login_username_logged_out, app->login_username_logged_in_temp_buffer_size - 1);
+            strncpy(app->login_username_logged_in_temp_buffer, app->login_username_logged_out, app->login_username_logged_in_temp_buffer_size - 1);
             app->login_username_logged_in[app->login_username_logged_in_temp_buffer_size - 1] = '\0';
+            app->login_username_logged_in_temp_buffer[app->login_username_logged_in_temp_buffer_size - 1] = '\0';
+        }
+        // logout username is empty but logged in isnt, copy it over
+        if (strlen(app->login_username_logged_in) > 0 && strlen(app->login_username_logged_out) == 0)
+        {
+            strncpy(app->login_username_logged_out, app->login_username_logged_in, app->login_username_logged_in_temp_buffer_size - 1);
+            strncpy(app->login_username_logged_out_temp_buffer, app->login_username_logged_in, app->login_username_logged_in_temp_buffer_size - 1);
+            app->login_username_logged_out[app->login_username_logged_in_temp_buffer_size - 1] = '\0';
+            app->login_username_logged_out_temp_buffer[app->login_username_logged_in_temp_buffer_size - 1] = '\0';
         }
         // if login password is empty but logged out isnt, copy it over
         if (strlen(app->login_password_logged_out) > 0 && strlen(app->change_password_logged_in) == 0)
         {
             strncpy(app->change_password_logged_in, app->login_password_logged_out, app->login_password_logged_out_temp_buffer_size - 1);
+            strncpy(app->change_password_logged_in_temp_buffer, app->login_password_logged_out, app->login_password_logged_out_temp_buffer_size - 1);
             app->change_password_logged_in[app->login_password_logged_out_temp_buffer_size - 1] = '\0';
+            app->change_password_logged_in_temp_buffer[app->login_password_logged_out_temp_buffer_size - 1] = '\0';
         }
+        // if logout password is empty but logged in isnt, copy it over
+        if (strlen(app->change_password_logged_in) > 0 && strlen(app->login_password_logged_out) == 0)
+        {
+            strncpy(app->login_password_logged_out, app->change_password_logged_in, app->login_password_logged_out_temp_buffer_size - 1);
+            strncpy(app->login_password_logged_out_temp_buffer, app->change_password_logged_in, app->login_password_logged_out_temp_buffer_size - 1);
+            app->login_password_logged_out[app->login_password_logged_out_temp_buffer_size - 1] = '\0';
+            app->login_password_logged_out_temp_buffer[app->login_password_logged_out_temp_buffer_size - 1] = '\0';
+        }
+        // if wifi password is empty but logged out isnt, copy it over
+        if (strlen(app->wifi_password_logged_out) > 0 && strlen(app->wifi_password_logged_in) == 0)
+        {
+            strncpy(app->wifi_password_logged_in, app->wifi_password_logged_out, app->wifi_password_logged_in_temp_buffer_size - 1);
+            strncpy(app->wifi_password_logged_in_temp_buffer, app->wifi_password_logged_out, app->wifi_password_logged_in_temp_buffer_size - 1);
+            app->wifi_password_logged_in[app->wifi_password_logged_in_temp_buffer_size - 1] = '\0';
+            app->wifi_password_logged_in_temp_buffer[app->wifi_password_logged_in_temp_buffer_size - 1] = '\0';
+        }
+        // ifi wifi password is empty but logged in isnt, copy it over
+        if (strlen(app->wifi_password_logged_in) > 0 && strlen(app->wifi_password_logged_out) == 0)
+        {
+            strncpy(app->wifi_password_logged_out, app->wifi_password_logged_in, app->wifi_password_logged_in_temp_buffer_size - 1);
+            strncpy(app->wifi_password_logged_out_temp_buffer, app->wifi_password_logged_in, app->wifi_password_logged_in_temp_buffer_size - 1);
+            app->wifi_password_logged_out[app->wifi_password_logged_in_temp_buffer_size - 1] = '\0';
+            app->wifi_password_logged_out_temp_buffer[app->wifi_password_logged_in_temp_buffer_size - 1] = '\0';
+        }
+        // if wifi ssid is empty but logged out isnt, copy it over
+        if (strlen(app->wifi_ssid_logged_out) > 0 && strlen(app->wifi_ssid_logged_in) == 0)
+        {
+            strncpy(app->wifi_ssid_logged_in, app->wifi_ssid_logged_out, app->wifi_ssid_logged_in_temp_buffer_size - 1);
+            strncpy(app->wifi_ssid_logged_in_temp_buffer, app->wifi_ssid_logged_out, app->wifi_ssid_logged_in_temp_buffer_size - 1);
+            app->wifi_ssid_logged_in[app->wifi_ssid_logged_in_temp_buffer_size - 1] = '\0';
+            app->wifi_ssid_logged_in_temp_buffer[app->wifi_ssid_logged_in_temp_buffer_size - 1] = '\0';
+        }
+        // if wifi ssid is empty but logged in isnt, copy it over
+        if (strlen(app->wifi_ssid_logged_in) > 0 && strlen(app->wifi_ssid_logged_out) == 0)
+        {
+            strncpy(app->wifi_ssid_logged_out, app->wifi_ssid_logged_in, app->wifi_ssid_logged_in_temp_buffer_size - 1);
+            strncpy(app->wifi_ssid_logged_out_temp_buffer, app->wifi_ssid_logged_in, app->wifi_ssid_logged_in_temp_buffer_size - 1);
+            app->wifi_ssid_logged_out[app->wifi_ssid_logged_in_temp_buffer_size - 1] = '\0';
+            app->wifi_ssid_logged_out_temp_buffer[app->wifi_ssid_logged_in_temp_buffer_size - 1] = '\0';
+        }
+
+        // set variable item text (ommit the passwords)
+        variable_item_set_current_value_text(app->variable_item_logged_in_wifi_settings_ssid, app->wifi_ssid_logged_in);
+        variable_item_set_current_value_text(app->variable_item_logged_out_wifi_settings_ssid, app->wifi_ssid_logged_out);
+        variable_item_set_current_value_text(app->variable_item_logged_out_login_username, app->login_username_logged_out);
+        variable_item_set_current_value_text(app->variable_item_logged_in_profile_username, app->login_username_logged_in);
+        //
 
         app_instance = app;
         if (app->is_logged_in != NULL && strcmp(app->is_logged_in, "true") == 0)

+ 0 - 2
flip_social_storage.h

@@ -139,8 +139,6 @@ bool load_playlist(PreSavedPlaylist *playlist)
         }
     }
 
-    FURI_LOG_I(TAG, "Playlist loaded: playlist_count=%zu", playlist->count);
-
     // Close the file and storage
     storage_file_close(file);
     storage_file_free(file);

+ 3 - 3
flipper_http.h

@@ -302,7 +302,7 @@ bool flipper_http_init(FlipperHTTP_Callback callback, void *context)
     // Set the timer thread priority if needed
     furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
 
-    FURI_LOG_I(HTTP_TAG, "UART initialized successfully.");
+    // FURI_LOG_I(HTTP_TAG, "UART initialized successfully.");
     return true;
 }
 
@@ -358,7 +358,7 @@ void flipper_http_deinit()
         fhttp.last_response = NULL;
     }
 
-    FURI_LOG_I("FlipperHTTP", "UART deinitialized successfully.");
+    // FURI_LOG_I("FlipperHTTP", "UART deinitialized successfully.");
 }
 
 // Function to send data over UART with newline termination
@@ -977,7 +977,7 @@ void flipper_http_rx_callback(const char *line, void *context)
     // Handle different types of responses
     if (strstr(line, "[SUCCESS]") != NULL || strstr(line, "[CONNECTED]") != NULL)
     {
-        FURI_LOG_I(HTTP_TAG, "Operation succeeded.");
+        // FURI_LOG_I(HTTP_TAG, "Operation succeeded.");
     }
     else if (strstr(line, "[INFO]") != NULL)
     {

+ 504 - 360
jsmn.h

@@ -27,7 +27,8 @@
 #include <stddef.h>
 
 #ifdef __cplusplus
-extern "C" {
+extern "C"
+{
 #endif
 
 #ifdef JSMN_STATIC
@@ -36,431 +37,487 @@ extern "C" {
 #define JSMN_API extern
 #endif
 
-/**
- * JSON type identifier. Basic types are:
- * 	o Object
- * 	o Array
- * 	o String
- * 	o Other primitive: number, boolean (true/false) or null
- */
-typedef enum {
-  JSMN_UNDEFINED = 0,
-  JSMN_OBJECT = 1 << 0,
-  JSMN_ARRAY = 1 << 1,
-  JSMN_STRING = 1 << 2,
-  JSMN_PRIMITIVE = 1 << 3
-} jsmntype_t;
-
-enum jsmnerr {
-  /* Not enough tokens were provided */
-  JSMN_ERROR_NOMEM = -1,
-  /* Invalid character inside JSON string */
-  JSMN_ERROR_INVAL = -2,
-  /* The string is not a full JSON packet, more bytes expected */
-  JSMN_ERROR_PART = -3
-};
-
-/**
- * JSON token description.
- * type		type (object, array, string etc.)
- * start	start position in JSON data string
- * end		end position in JSON data string
- */
-typedef struct jsmntok {
-  jsmntype_t type;
-  int start;
-  int end;
-  int size;
+  /**
+   * JSON type identifier. Basic types are:
+   * 	o Object
+   * 	o Array
+   * 	o String
+   * 	o Other primitive: number, boolean (true/false) or null
+   */
+  typedef enum
+  {
+    JSMN_UNDEFINED = 0,
+    JSMN_OBJECT = 1 << 0,
+    JSMN_ARRAY = 1 << 1,
+    JSMN_STRING = 1 << 2,
+    JSMN_PRIMITIVE = 1 << 3
+  } jsmntype_t;
+
+  enum jsmnerr
+  {
+    /* Not enough tokens were provided */
+    JSMN_ERROR_NOMEM = -1,
+    /* Invalid character inside JSON string */
+    JSMN_ERROR_INVAL = -2,
+    /* The string is not a full JSON packet, more bytes expected */
+    JSMN_ERROR_PART = -3
+  };
+
+  /**
+   * JSON token description.
+   * type		type (object, array, string etc.)
+   * start	start position in JSON data string
+   * end		end position in JSON data string
+   */
+  typedef struct jsmntok
+  {
+    jsmntype_t type;
+    int start;
+    int end;
+    int size;
 #ifdef JSMN_PARENT_LINKS
-  int parent;
+    int parent;
 #endif
-} jsmntok_t;
+  } jsmntok_t;
 
-/**
- * JSON parser. Contains an array of token blocks available. Also stores
- * the string being parsed now and current position in that string.
- */
-typedef struct jsmn_parser {
-  unsigned int pos;     /* offset in the JSON string */
-  unsigned int toknext; /* next token to allocate */
-  int toksuper;         /* superior token node, e.g. parent object or array */
-} jsmn_parser;
-
-/**
- * Create JSON parser over an array of tokens
- */
-JSMN_API void jsmn_init(jsmn_parser *parser);
+  /**
+   * JSON parser. Contains an array of token blocks available. Also stores
+   * the string being parsed now and current position in that string.
+   */
+  typedef struct jsmn_parser
+  {
+    unsigned int pos;     /* offset in the JSON string */
+    unsigned int toknext; /* next token to allocate */
+    int toksuper;         /* superior token node, e.g. parent object or array */
+  } jsmn_parser;
 
-/**
- * Run JSON parser. It parses a JSON data string into and array of tokens, each
- * describing
- * a single JSON object.
- */
-JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
-                        jsmntok_t *tokens, const unsigned int num_tokens);
+  /**
+   * Create JSON parser over an array of tokens
+   */
+  JSMN_API void jsmn_init(jsmn_parser *parser);
+
+  /**
+   * Run JSON parser. It parses a JSON data string into and array of tokens, each
+   * describing
+   * a single JSON object.
+   */
+  JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
+                          jsmntok_t *tokens, const unsigned int num_tokens);
 
 #ifndef JSMN_HEADER
-/**
- * Allocates a fresh unused token from the token pool.
- */
-static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens,
-                                   const size_t num_tokens) {
-  jsmntok_t *tok;
-  if (parser->toknext >= num_tokens) {
-    return NULL;
-  }
-  tok = &tokens[parser->toknext++];
-  tok->start = tok->end = -1;
-  tok->size = 0;
+  /**
+   * Allocates a fresh unused token from the token pool.
+   */
+  static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens,
+                                     const size_t num_tokens)
+  {
+    jsmntok_t *tok;
+    if (parser->toknext >= num_tokens)
+    {
+      return NULL;
+    }
+    tok = &tokens[parser->toknext++];
+    tok->start = tok->end = -1;
+    tok->size = 0;
 #ifdef JSMN_PARENT_LINKS
-  tok->parent = -1;
+    tok->parent = -1;
 #endif
-  return tok;
-}
+    return tok;
+  }
 
-/**
- * Fills token type and boundaries.
- */
-static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type,
-                            const int start, const int end) {
-  token->type = type;
-  token->start = start;
-  token->end = end;
-  token->size = 0;
-}
+  /**
+   * Fills token type and boundaries.
+   */
+  static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type,
+                              const int start, const int end)
+  {
+    token->type = type;
+    token->start = start;
+    token->end = end;
+    token->size = 0;
+  }
 
-/**
- * Fills next available token with JSON primitive.
- */
-static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
-                                const size_t len, jsmntok_t *tokens,
-                                const size_t num_tokens) {
-  jsmntok_t *token;
-  int start;
+  /**
+   * Fills next available token with JSON primitive.
+   */
+  static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+                                  const size_t len, jsmntok_t *tokens,
+                                  const size_t num_tokens)
+  {
+    jsmntok_t *token;
+    int start;
 
-  start = parser->pos;
+    start = parser->pos;
 
-  for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
-    switch (js[parser->pos]) {
+    for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++)
+    {
+      switch (js[parser->pos])
+      {
 #ifndef JSMN_STRICT
-    /* In strict mode primitive must be followed by "," or "}" or "]" */
-    case ':':
+      /* In strict mode primitive must be followed by "," or "}" or "]" */
+      case ':':
 #endif
-    case '\t':
-    case '\r':
-    case '\n':
-    case ' ':
-    case ',':
-    case ']':
-    case '}':
-      goto found;
-    default:
-                   /* to quiet a warning from gcc*/
-      break;
-    }
-    if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
-      parser->pos = start;
-      return JSMN_ERROR_INVAL;
+      case '\t':
+      case '\r':
+      case '\n':
+      case ' ':
+      case ',':
+      case ']':
+      case '}':
+        goto found;
+      default:
+        /* to quiet a warning from gcc*/
+        break;
+      }
+      if (js[parser->pos] < 32 || js[parser->pos] >= 127)
+      {
+        parser->pos = start;
+        return JSMN_ERROR_INVAL;
+      }
     }
-  }
 #ifdef JSMN_STRICT
-  /* In strict mode primitive must be followed by a comma/object/array */
-  parser->pos = start;
-  return JSMN_ERROR_PART;
+    /* In strict mode primitive must be followed by a comma/object/array */
+    parser->pos = start;
+    return JSMN_ERROR_PART;
 #endif
 
-found:
-  if (tokens == NULL) {
+  found:
+    if (tokens == NULL)
+    {
+      parser->pos--;
+      return 0;
+    }
+    token = jsmn_alloc_token(parser, tokens, num_tokens);
+    if (token == NULL)
+    {
+      parser->pos = start;
+      return JSMN_ERROR_NOMEM;
+    }
+    jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+    token->parent = parser->toksuper;
+#endif
     parser->pos--;
     return 0;
   }
-  token = jsmn_alloc_token(parser, tokens, num_tokens);
-  if (token == NULL) {
-    parser->pos = start;
-    return JSMN_ERROR_NOMEM;
-  }
-  jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+
+  /**
+   * Fills next token with JSON string.
+   */
+  static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+                               const size_t len, jsmntok_t *tokens,
+                               const size_t num_tokens)
+  {
+    jsmntok_t *token;
+
+    int start = parser->pos;
+
+    /* Skip starting quote */
+    parser->pos++;
+
+    for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++)
+    {
+      char c = js[parser->pos];
+
+      /* Quote: end of string */
+      if (c == '\"')
+      {
+        if (tokens == NULL)
+        {
+          return 0;
+        }
+        token = jsmn_alloc_token(parser, tokens, num_tokens);
+        if (token == NULL)
+        {
+          parser->pos = start;
+          return JSMN_ERROR_NOMEM;
+        }
+        jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos);
 #ifdef JSMN_PARENT_LINKS
-  token->parent = parser->toksuper;
+        token->parent = parser->toksuper;
 #endif
-  parser->pos--;
-  return 0;
-}
-
-/**
- * Fills next token with JSON string.
- */
-static int jsmn_parse_string(jsmn_parser *parser, const char *js,
-                             const size_t len, jsmntok_t *tokens,
-                             const size_t num_tokens) {
-  jsmntok_t *token;
-
-  int start = parser->pos;
-  
-  /* Skip starting quote */
-  parser->pos++;
-  
-  for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
-    char c = js[parser->pos];
-
-    /* Quote: end of string */
-    if (c == '\"') {
-      if (tokens == NULL) {
         return 0;
       }
-      token = jsmn_alloc_token(parser, tokens, num_tokens);
-      if (token == NULL) {
-        parser->pos = start;
-        return JSMN_ERROR_NOMEM;
-      }
-      jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos);
-#ifdef JSMN_PARENT_LINKS
-      token->parent = parser->toksuper;
-#endif
-      return 0;
-    }
 
-    /* Backslash: Quoted symbol expected */
-    if (c == '\\' && parser->pos + 1 < len) {
-      int i;
-      parser->pos++;
-      switch (js[parser->pos]) {
-      /* Allowed escaped symbols */
-      case '\"':
-      case '/':
-      case '\\':
-      case 'b':
-      case 'f':
-      case 'r':
-      case 'n':
-      case 't':
-        break;
-      /* Allows escaped symbol \uXXXX */
-      case 'u':
+      /* Backslash: Quoted symbol expected */
+      if (c == '\\' && parser->pos + 1 < len)
+      {
+        int i;
         parser->pos++;
-        for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0';
-             i++) {
-          /* If it isn't a hex character we have an error */
-          if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) ||   /* 0-9 */
-                (js[parser->pos] >= 65 && js[parser->pos] <= 70) ||   /* A-F */
-                (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
-            parser->pos = start;
-            return JSMN_ERROR_INVAL;
-          }
+        switch (js[parser->pos])
+        {
+        /* Allowed escaped symbols */
+        case '\"':
+        case '/':
+        case '\\':
+        case 'b':
+        case 'f':
+        case 'r':
+        case 'n':
+        case 't':
+          break;
+        /* Allows escaped symbol \uXXXX */
+        case 'u':
           parser->pos++;
+          for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0';
+               i++)
+          {
+            /* If it isn't a hex character we have an error */
+            if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+                  (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+                  (js[parser->pos] >= 97 && js[parser->pos] <= 102)))
+            { /* a-f */
+              parser->pos = start;
+              return JSMN_ERROR_INVAL;
+            }
+            parser->pos++;
+          }
+          parser->pos--;
+          break;
+        /* Unexpected symbol */
+        default:
+          parser->pos = start;
+          return JSMN_ERROR_INVAL;
         }
-        parser->pos--;
-        break;
-      /* Unexpected symbol */
-      default:
-        parser->pos = start;
-        return JSMN_ERROR_INVAL;
       }
     }
+    parser->pos = start;
+    return JSMN_ERROR_PART;
   }
-  parser->pos = start;
-  return JSMN_ERROR_PART;
-}
 
-/**
- * Parse JSON string and fill tokens.
- */
-JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
-                        jsmntok_t *tokens, const unsigned int num_tokens) {
-  int r;
-  int i;
-  jsmntok_t *token;
-  int count = parser->toknext;
-
-  for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
-    char c;
-    jsmntype_t type;
+  /**
+   * Parse JSON string and fill tokens.
+   */
+  JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
+                          jsmntok_t *tokens, const unsigned int num_tokens)
+  {
+    int r;
+    int i;
+    jsmntok_t *token;
+    int count = parser->toknext;
 
-    c = js[parser->pos];
-    switch (c) {
-    case '{':
-    case '[':
-      count++;
-      if (tokens == NULL) {
-        break;
-      }
-      token = jsmn_alloc_token(parser, tokens, num_tokens);
-      if (token == NULL) {
-        return JSMN_ERROR_NOMEM;
-      }
-      if (parser->toksuper != -1) {
-        jsmntok_t *t = &tokens[parser->toksuper];
-#ifdef JSMN_STRICT
-        /* In strict mode an object or array can't become a key */
-        if (t->type == JSMN_OBJECT) {
-          return JSMN_ERROR_INVAL;
+    for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++)
+    {
+      char c;
+      jsmntype_t type;
+
+      c = js[parser->pos];
+      switch (c)
+      {
+      case '{':
+      case '[':
+        count++;
+        if (tokens == NULL)
+        {
+          break;
+        }
+        token = jsmn_alloc_token(parser, tokens, num_tokens);
+        if (token == NULL)
+        {
+          return JSMN_ERROR_NOMEM;
         }
+        if (parser->toksuper != -1)
+        {
+          jsmntok_t *t = &tokens[parser->toksuper];
+#ifdef JSMN_STRICT
+          /* In strict mode an object or array can't become a key */
+          if (t->type == JSMN_OBJECT)
+          {
+            return JSMN_ERROR_INVAL;
+          }
 #endif
-        t->size++;
+          t->size++;
 #ifdef JSMN_PARENT_LINKS
-        token->parent = parser->toksuper;
+          token->parent = parser->toksuper;
 #endif
-      }
-      token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
-      token->start = parser->pos;
-      parser->toksuper = parser->toknext - 1;
-      break;
-    case '}':
-    case ']':
-      if (tokens == NULL) {
+        }
+        token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+        token->start = parser->pos;
+        parser->toksuper = parser->toknext - 1;
         break;
-      }
-      type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
-#ifdef JSMN_PARENT_LINKS
-      if (parser->toknext < 1) {
-        return JSMN_ERROR_INVAL;
-      }
-      token = &tokens[parser->toknext - 1];
-      for (;;) {
-        if (token->start != -1 && token->end == -1) {
-          if (token->type != type) {
-            return JSMN_ERROR_INVAL;
-          }
-          token->end = parser->pos + 1;
-          parser->toksuper = token->parent;
+      case '}':
+      case ']':
+        if (tokens == NULL)
+        {
           break;
         }
-        if (token->parent == -1) {
-          if (token->type != type || parser->toksuper == -1) {
-            return JSMN_ERROR_INVAL;
+        type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+        if (parser->toknext < 1)
+        {
+          return JSMN_ERROR_INVAL;
+        }
+        token = &tokens[parser->toknext - 1];
+        for (;;)
+        {
+          if (token->start != -1 && token->end == -1)
+          {
+            if (token->type != type)
+            {
+              return JSMN_ERROR_INVAL;
+            }
+            token->end = parser->pos + 1;
+            parser->toksuper = token->parent;
+            break;
           }
-          break;
+          if (token->parent == -1)
+          {
+            if (token->type != type || parser->toksuper == -1)
+            {
+              return JSMN_ERROR_INVAL;
+            }
+            break;
+          }
+          token = &tokens[token->parent];
         }
-        token = &tokens[token->parent];
-      }
 #else
-      for (i = parser->toknext - 1; i >= 0; i--) {
-        token = &tokens[i];
-        if (token->start != -1 && token->end == -1) {
-          if (token->type != type) {
-            return JSMN_ERROR_INVAL;
+        for (i = parser->toknext - 1; i >= 0; i--)
+        {
+          token = &tokens[i];
+          if (token->start != -1 && token->end == -1)
+          {
+            if (token->type != type)
+            {
+              return JSMN_ERROR_INVAL;
+            }
+            parser->toksuper = -1;
+            token->end = parser->pos + 1;
+            break;
           }
-          parser->toksuper = -1;
-          token->end = parser->pos + 1;
-          break;
         }
-      }
-      /* Error if unmatched closing bracket */
-      if (i == -1) {
-        return JSMN_ERROR_INVAL;
-      }
-      for (; i >= 0; i--) {
-        token = &tokens[i];
-        if (token->start != -1 && token->end == -1) {
-          parser->toksuper = i;
-          break;
+        /* Error if unmatched closing bracket */
+        if (i == -1)
+        {
+          return JSMN_ERROR_INVAL;
+        }
+        for (; i >= 0; i--)
+        {
+          token = &tokens[i];
+          if (token->start != -1 && token->end == -1)
+          {
+            parser->toksuper = i;
+            break;
+          }
         }
-      }
 #endif
-      break;
-    case '\"':
-      r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
-      if (r < 0) {
-        return r;
-      }
-      count++;
-      if (parser->toksuper != -1 && tokens != NULL) {
-        tokens[parser->toksuper].size++;
-      }
-      break;
-    case '\t':
-    case '\r':
-    case '\n':
-    case ' ':
-      break;
-    case ':':
-      parser->toksuper = parser->toknext - 1;
-      break;
-    case ',':
-      if (tokens != NULL && parser->toksuper != -1 &&
-          tokens[parser->toksuper].type != JSMN_ARRAY &&
-          tokens[parser->toksuper].type != JSMN_OBJECT) {
+        break;
+      case '\"':
+        r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+        if (r < 0)
+        {
+          return r;
+        }
+        count++;
+        if (parser->toksuper != -1 && tokens != NULL)
+        {
+          tokens[parser->toksuper].size++;
+        }
+        break;
+      case '\t':
+      case '\r':
+      case '\n':
+      case ' ':
+        break;
+      case ':':
+        parser->toksuper = parser->toknext - 1;
+        break;
+      case ',':
+        if (tokens != NULL && parser->toksuper != -1 &&
+            tokens[parser->toksuper].type != JSMN_ARRAY &&
+            tokens[parser->toksuper].type != JSMN_OBJECT)
+        {
 #ifdef JSMN_PARENT_LINKS
-        parser->toksuper = tokens[parser->toksuper].parent;
+          parser->toksuper = tokens[parser->toksuper].parent;
 #else
-        for (i = parser->toknext - 1; i >= 0; i--) {
-          if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
-            if (tokens[i].start != -1 && tokens[i].end == -1) {
-              parser->toksuper = i;
-              break;
+          for (i = parser->toknext - 1; i >= 0; i--)
+          {
+            if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT)
+            {
+              if (tokens[i].start != -1 && tokens[i].end == -1)
+              {
+                parser->toksuper = i;
+                break;
+              }
             }
           }
-        }
 #endif
-      }
-      break;
+        }
+        break;
 #ifdef JSMN_STRICT
-    /* In strict mode primitives are: numbers and booleans */
-    case '-':
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':
-    case 't':
-    case 'f':
-    case 'n':
-      /* And they must not be keys of the object */
-      if (tokens != NULL && parser->toksuper != -1) {
-        const jsmntok_t *t = &tokens[parser->toksuper];
-        if (t->type == JSMN_OBJECT ||
-            (t->type == JSMN_STRING && t->size != 0)) {
-          return JSMN_ERROR_INVAL;
+      /* In strict mode primitives are: numbers and booleans */
+      case '-':
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+      case 't':
+      case 'f':
+      case 'n':
+        /* And they must not be keys of the object */
+        if (tokens != NULL && parser->toksuper != -1)
+        {
+          const jsmntok_t *t = &tokens[parser->toksuper];
+          if (t->type == JSMN_OBJECT ||
+              (t->type == JSMN_STRING && t->size != 0))
+          {
+            return JSMN_ERROR_INVAL;
+          }
         }
-      }
 #else
-    /* In non-strict mode every unquoted value is a primitive */
-    default:
+      /* In non-strict mode every unquoted value is a primitive */
+      default:
 #endif
-      r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
-      if (r < 0) {
-        return r;
-      }
-      count++;
-      if (parser->toksuper != -1 && tokens != NULL) {
-        tokens[parser->toksuper].size++;
-      }
-      break;
+        r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+        if (r < 0)
+        {
+          return r;
+        }
+        count++;
+        if (parser->toksuper != -1 && tokens != NULL)
+        {
+          tokens[parser->toksuper].size++;
+        }
+        break;
 
 #ifdef JSMN_STRICT
-    /* Unexpected char in strict mode */
-    default:
-      return JSMN_ERROR_INVAL;
+      /* Unexpected char in strict mode */
+      default:
+        return JSMN_ERROR_INVAL;
 #endif
+      }
     }
-  }
 
-  if (tokens != NULL) {
-    for (i = parser->toknext - 1; i >= 0; i--) {
-      /* Unmatched opened object or array */
-      if (tokens[i].start != -1 && tokens[i].end == -1) {
-        return JSMN_ERROR_PART;
+    if (tokens != NULL)
+    {
+      for (i = parser->toknext - 1; i >= 0; i--)
+      {
+        /* Unmatched opened object or array */
+        if (tokens[i].start != -1 && tokens[i].end == -1)
+        {
+          return JSMN_ERROR_PART;
+        }
       }
     }
-  }
 
-  return count;
-}
+    return count;
+  }
 
-/**
- * Creates a new parser based over a given buffer with an array of tokens
- * available.
- */
-JSMN_API void jsmn_init(jsmn_parser *parser) {
-  parser->pos = 0;
-  parser->toknext = 0;
-  parser->toksuper = -1;
-}
+  /**
+   * Creates a new parser based over a given buffer with an array of tokens
+   * available.
+   */
+  JSMN_API void jsmn_init(jsmn_parser *parser)
+  {
+    parser->pos = 0;
+    parser->toknext = 0;
+    parser->toksuper = -1;
+  }
 
 #endif /* JSMN_HEADER */
 
@@ -469,3 +526,90 @@ JSMN_API void jsmn_init(jsmn_parser *parser) {
 #endif
 
 #endif /* JSMN_H */
+
+/* Added in by JBlanked on 2024-10-16 for use in Flipper Zero SDK*/
+
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <furi.h>
+
+// Helper function to compare JSON keys
+int jsoneq(const char *json, jsmntok_t *tok, const char *s)
+{
+  if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start &&
+      strncmp(json + tok->start, s, tok->end - tok->start) == 0)
+  {
+    return 0;
+  }
+  return -1;
+}
+
+// return the value of the key in the JSON data
+// works for the first level of the JSON data
+char *get_json_value(char *key, char *json_data, uint32_t max_tokens)
+{
+  // Parse the JSON feed
+  if (json_data != NULL)
+  {
+    jsmn_parser parser;
+    jsmn_init(&parser);
+
+    // Allocate tokens array on the heap
+    jsmntok_t *tokens = malloc(sizeof(jsmntok_t) * max_tokens);
+    if (tokens == NULL)
+    {
+      FURI_LOG_E("JSMM.H", "Failed to allocate memory for JSON tokens.");
+      return NULL;
+    }
+
+    int ret = jsmn_parse(&parser, json_data, strlen(json_data), tokens, max_tokens);
+    if (ret < 0)
+    {
+      // Handle parsing errors
+      FURI_LOG_E("JSMM.H", "Failed to parse JSON: %d", ret);
+      free(tokens);
+      return NULL;
+    }
+
+    // Ensure that the root element is an object
+    if (ret < 1 || tokens[0].type != JSMN_OBJECT)
+    {
+      FURI_LOG_E("JSMM.H", "Root element is not an object.");
+      free(tokens);
+      return NULL;
+    }
+
+    // Loop through the tokens to find the key
+    for (int i = 1; i < ret; i++)
+    {
+      if (jsoneq(json_data, &tokens[i], key) == 0)
+      {
+        // We found the key. Now, return the associated value.
+        int length = tokens[i + 1].end - tokens[i + 1].start;
+        char *value = malloc(length + 1);
+        if (value == NULL)
+        {
+          FURI_LOG_E("JSMM.H", "Failed to allocate memory for value.");
+          free(tokens);
+          return NULL;
+        }
+        strncpy(value, json_data + tokens[i + 1].start, length);
+        value[length] = '\0'; // Null-terminate the string
+
+        free(tokens); // Free the token array
+        return value; // Return the extracted value
+      }
+    }
+
+    // Free the token array if key was not found
+    free(tokens);
+  }
+  else
+  {
+    FURI_LOG_E("JSMM.H", "JSON data is NULL");
+  }
+  FURI_LOG_E("JSMM.H", "Failed to find the key in the JSON.");
+  return NULL; // Return NULL if something goes wrong
+}