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

Implemented exit button behavior setting

Sandro Kalatozishvili 2 лет назад
Родитель
Сommit
2df6dd0b32

+ 4 - 3
README.md

@@ -53,13 +53,14 @@ Button name | Description
     - [ ] Full button list
     - [ ] Full button list
     - [ ] Edit remote file
     - [ ] Edit remote file
     - [ ] Delete remote file
     - [ ] Delete remote file
+    - [ ] Horizontal view for all pages
 - [x] Application settings
 - [x] Application settings
+    - [x] GUI to change settings
     - [x] Load settings from the file
     - [x] Load settings from the file
     - [x] Store settings to the file
     - [x] Store settings to the file
-    - [x] Vertical/Horizontal menu
+    - [x] Vertical/Horizontal view
     - [x] IR command repeat count
     - [x] IR command repeat count
-    - [x] GUI to change settings
-    - [ ] Return button configuration
+    - [x] Exit button behavior
 
 
 ## Screens
 ## Screens
 
 

+ 3 - 3
views/xremote_about_view.c

@@ -33,8 +33,8 @@ static void xremote_about_view_draw_callback(Canvas* canvas, void* context)
     xremote_canvas_draw_exit_footer(canvas, "Press to exit");
     xremote_canvas_draw_exit_footer(canvas, "Press to exit");
 }
 }
 
 
-XRemoteView* xremote_about_view_alloc(NotificationApp* notifications)
+XRemoteView* xremote_about_view_alloc(void *app_ctx)
 {
 {
-    return xremote_view_alloc(notifications,
-        NULL, xremote_about_view_draw_callback);
+    return xremote_view_alloc(app_ctx, NULL,
+        xremote_about_view_draw_callback);
 }
 }

+ 1 - 1
views/xremote_about_view.h

@@ -10,4 +10,4 @@
 
 
 #include "xremote_common_view.h"
 #include "xremote_common_view.h"
 
 
-XRemoteView* xremote_about_view_alloc(NotificationApp* notifications);
+XRemoteView* xremote_about_view_alloc(void* app_ctx);

+ 12 - 5
views/xremote_common_view.c

@@ -13,7 +13,7 @@
 
 
 struct XRemoteView {
 struct XRemoteView {
     XRemoteViewClearCallback on_clear;
     XRemoteViewClearCallback on_clear;
-    NotificationApp* notifications;
+    XRemoteAppContext* app_ctx;
     View* view;
     View* view;
     void *context;
     void *context;
 };
 };
@@ -25,11 +25,11 @@ const NotificationSequence g_sequence_blink_purple_50 = {
     NULL,
     NULL,
 };
 };
 
 
-XRemoteView* xremote_view_alloc(NotificationApp* notifications, ViewInputCallback input_cb, ViewDrawCallback draw_cb)
+XRemoteView* xremote_view_alloc(void* app_ctx, ViewInputCallback input_cb, ViewDrawCallback draw_cb)
 {
 {
     XRemoteView* remote_view = malloc(sizeof(XRemoteView));
     XRemoteView* remote_view = malloc(sizeof(XRemoteView));
+    remote_view->app_ctx = app_ctx;
     remote_view->view = view_alloc();
     remote_view->view = view_alloc();
-    remote_view->notifications = notifications;
 
 
     remote_view->context = NULL;
     remote_view->context = NULL;
     remote_view->on_clear = NULL;
     remote_view->on_clear = NULL;
@@ -70,6 +70,12 @@ void* xremote_view_get_context(XRemoteView* rview)
     return rview->context;
     return rview->context;
 }
 }
 
 
+void* xremote_view_get_app_context(XRemoteView* rview)
+{
+    furi_assert(rview);
+    return rview->app_ctx;
+}
+
 void xremote_view_free(XRemoteView* rview)
 void xremote_view_free(XRemoteView* rview)
 {
 {
     furi_assert(rview);
     furi_assert(rview);
@@ -100,7 +106,8 @@ void xremote_view_send_ir(XRemoteView *rview, const char *name)
     xremote_app_assert_void(signal);
     xremote_app_assert_void(signal);
 
 
     infrared_signal_transmit(signal);
     infrared_signal_transmit(signal);
-    notification_message(rview->notifications, &g_sequence_blink_purple_50);
+    NotificationApp* notifications = rview->app_ctx->notifications;
+    notification_message(notifications, &g_sequence_blink_purple_50);
 }
 }
 
 
 void xremote_canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, XRemoteIcon icon)
 void xremote_canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, XRemoteIcon icon)
@@ -199,7 +206,7 @@ void xremote_canvas_draw_header(Canvas* canvas, const char* section)
     canvas_draw_str(canvas, 0, 20, section);
     canvas_draw_str(canvas, 0, 20, section);
 }
 }
 
 
-void xremote_canvas_draw_exit_footer(Canvas* canvas, char *text)
+void xremote_canvas_draw_exit_footer(Canvas* canvas, const char *text)
 {
 {
     canvas_set_font(canvas, FontSecondary);
     canvas_set_font(canvas, FontSecondary);
     xremote_canvas_draw_icon(canvas, 6, 124, XRemoteIconBack);
     xremote_canvas_draw_icon(canvas, 6, 124, XRemoteIconBack);

+ 5 - 4
views/xremote_common_view.h

@@ -73,7 +73,7 @@ typedef struct {
     bool down_pressed;
     bool down_pressed;
     bool left_pressed;
     bool left_pressed;
     bool right_pressed;
     bool right_pressed;
-    uint32_t reserverd;
+    void* context;
 } XRemoteViewModel;
 } XRemoteViewModel;
 
 
 typedef enum {
 typedef enum {
@@ -99,14 +99,14 @@ typedef struct XRemoteView XRemoteView;
 typedef void (*XRemoteViewClearCallback)(void *context);
 typedef void (*XRemoteViewClearCallback)(void *context);
 
 
 void xremote_canvas_draw_header(Canvas* canvas, const char* section);
 void xremote_canvas_draw_header(Canvas* canvas, const char* section);
-void xremote_canvas_draw_exit_footer(Canvas* canvas, char *text);
+void xremote_canvas_draw_exit_footer(Canvas* canvas, const char *text);
 
 
 void xremote_canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, XRemoteIcon icon);
 void xremote_canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, XRemoteIcon icon);
 void xremote_canvas_draw_button(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, XRemoteIcon icon);
 void xremote_canvas_draw_button(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, XRemoteIcon icon);
 void xremote_canvas_draw_button_wide(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, char* text, XRemoteIcon icon);
 void xremote_canvas_draw_button_wide(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, char* text, XRemoteIcon icon);
 void xremote_canvas_draw_frame(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, uint8_t xl, const char *text);
 void xremote_canvas_draw_frame(Canvas* canvas, bool pressed, uint8_t x, uint8_t y, uint8_t xl, const char *text);
 
 
-XRemoteView* xremote_view_alloc(NotificationApp* notifications, ViewInputCallback input_cb, ViewDrawCallback draw_cb);
+XRemoteView* xremote_view_alloc(void *app_ctx, ViewInputCallback input_cb, ViewDrawCallback draw_cb);
 void xremote_view_free(XRemoteView* rview);
 void xremote_view_free(XRemoteView* rview);
 
 
 View* xremote_view_get_view(XRemoteView* rview);
 View* xremote_view_get_view(XRemoteView* rview);
@@ -114,4 +114,5 @@ void xremote_view_send_ir(XRemoteView *rview, const char *name);
 
 
 void xremote_view_set_context(XRemoteView* rview, void *context, XRemoteViewClearCallback on_clear);
 void xremote_view_set_context(XRemoteView* rview, void *context, XRemoteViewClearCallback on_clear);
 void* xremote_view_get_context(XRemoteView* rview);
 void* xremote_view_get_context(XRemoteView* rview);
-void xremote_view_clear_context(XRemoteView* rview);
+void xremote_view_clear_context(XRemoteView* rview);
+void* xremote_view_get_app_context(XRemoteView* rview);

+ 2 - 2
views/xremote_control_view.c

@@ -78,9 +78,9 @@ static bool xremote_control_view_input_callback(InputEvent* event, void* context
     return true;
     return true;
 }
 }
 
 
-XRemoteView* xremote_control_view_alloc(NotificationApp* notifications)
+XRemoteView* xremote_control_view_alloc(void *app_ctx)
 {
 {
-    return xremote_view_alloc(notifications,
+    return xremote_view_alloc(app_ctx,
         xremote_control_view_input_callback,
         xremote_control_view_input_callback,
         xremote_control_view_draw_callback);
         xremote_control_view_draw_callback);
 }
 }

+ 1 - 1
views/xremote_control_view.h

@@ -10,4 +10,4 @@
 
 
 #include "xremote_common_view.h"
 #include "xremote_common_view.h"
 
 
-XRemoteView* xremote_control_view_alloc(NotificationApp* notifications);
+XRemoteView* xremote_control_view_alloc(void* app_ctx);

+ 3 - 3
views/xremote_custom_view.c

@@ -17,8 +17,8 @@ static void xremote_custom_view_draw_callback(Canvas* canvas, void* context)
     xremote_canvas_draw_exit_footer(canvas, "Press to exit");
     xremote_canvas_draw_exit_footer(canvas, "Press to exit");
 }
 }
 
 
-XRemoteView* xremote_custom_view_alloc(NotificationApp* notifications)
+XRemoteView* xremote_custom_view_alloc(void* app_ctx)
 {
 {
-    return xremote_view_alloc(notifications,
-        NULL, xremote_custom_view_draw_callback);
+    return xremote_view_alloc(app_ctx, NULL,
+        xremote_custom_view_draw_callback);
 }
 }

+ 1 - 1
views/xremote_custom_view.h

@@ -10,4 +10,4 @@
 
 
 #include "xremote_common_view.h"
 #include "xremote_common_view.h"
 
 
-XRemoteView* xremote_custom_view_alloc(NotificationApp* notifications);
+XRemoteView* xremote_custom_view_alloc(void* app_ctx);

+ 2 - 2
views/xremote_general_view.c

@@ -78,9 +78,9 @@ static bool xremote_general_view_input_callback(InputEvent* event, void* context
     return true;
     return true;
 }
 }
 
 
-XRemoteView* xremote_general_view_alloc(NotificationApp* notifications)
+XRemoteView* xremote_general_view_alloc(void* app_ctx)
 {
 {
-    return xremote_view_alloc(notifications,
+    return xremote_view_alloc(app_ctx,
         xremote_general_view_input_callback,
         xremote_general_view_input_callback,
         xremote_general_view_draw_callback);
         xremote_general_view_draw_callback);
 }
 }

+ 1 - 1
views/xremote_general_view.h

@@ -10,4 +10,4 @@
 
 
 #include "xremote_common_view.h"
 #include "xremote_common_view.h"
 
 
-XRemoteView* xremote_general_view_alloc(NotificationApp* notifications);
+XRemoteView* xremote_general_view_alloc(void* app_ctx);

+ 3 - 3
views/xremote_learn_view.c

@@ -17,8 +17,8 @@ static void xremote_learn_view_draw_callback(Canvas* canvas, void* context)
     xremote_canvas_draw_exit_footer(canvas, "Press to exit");
     xremote_canvas_draw_exit_footer(canvas, "Press to exit");
 }
 }
 
 
-XRemoteView* xremote_learn_view_alloc(NotificationApp* notifications)
+XRemoteView* xremote_learn_view_alloc(void* app_ctx)
 {
 {
-    return xremote_view_alloc(notifications,
-        NULL, xremote_learn_view_draw_callback);
+    return xremote_view_alloc(app_ctx, NULL,
+        xremote_learn_view_draw_callback);
 }
 }

+ 1 - 1
views/xremote_learn_view.h

@@ -10,4 +10,4 @@
 
 
 #include "xremote_common_view.h"
 #include "xremote_common_view.h"
 
 
-XRemoteView* xremote_learn_view_alloc(NotificationApp* notifications);
+XRemoteView* xremote_learn_view_alloc(void* app_ctx);

+ 36 - 6
views/xremote_navigation_view.c

@@ -7,11 +7,13 @@
  */
  */
 
 
 #include "xremote_navigation_view.h"
 #include "xremote_navigation_view.h"
+#include "../xremote_app.h"
 
 
 static void xremote_navigation_view_draw_callback(Canvas* canvas, void* context)
 static void xremote_navigation_view_draw_callback(Canvas* canvas, void* context)
 {
 {
     furi_assert(context);
     furi_assert(context);
     XRemoteViewModel* model = context;
     XRemoteViewModel* model = context;
+    XRemoteAppContext *app_ctx = model->context;
 
 
     xremote_canvas_draw_header(canvas, "Navigation");
     xremote_canvas_draw_header(canvas, "Navigation");
     xremote_canvas_draw_button(canvas, model->up_pressed, 23, 30, XRemoteIconArrowUp);
     xremote_canvas_draw_button(canvas, model->up_pressed, 23, 30, XRemoteIconArrowUp);
@@ -19,8 +21,13 @@ static void xremote_navigation_view_draw_callback(Canvas* canvas, void* context)
     xremote_canvas_draw_button(canvas, model->left_pressed, 2, 51, XRemoteIconArrowLeft);
     xremote_canvas_draw_button(canvas, model->left_pressed, 2, 51, XRemoteIconArrowLeft);
     xremote_canvas_draw_button(canvas, model->right_pressed, 44, 51, XRemoteIconArrowRight);
     xremote_canvas_draw_button(canvas, model->right_pressed, 44, 51, XRemoteIconArrowRight);
     xremote_canvas_draw_button(canvas, model->ok_pressed, 23, 51, XRemoteIconOk);
     xremote_canvas_draw_button(canvas, model->ok_pressed, 23, 51, XRemoteIconOk);
-    xremote_canvas_draw_button_wide(canvas, model->back_pressed, 0, 95, "Back", XRemoteIconBack);
-    xremote_canvas_draw_exit_footer(canvas, "Hold to exit");
+
+    if (app_ctx && app_ctx->app_settings->exit_behavior == XRemoteAppExitHold)
+        xremote_canvas_draw_button_wide(canvas, model->back_pressed, 0, 95, "Back", XRemoteIconBack);
+    else
+        xremote_canvas_draw_button_wide(canvas, model->back_pressed, 0, 95, "Hold", XRemoteIconBack);
+
+    xremote_canvas_draw_exit_footer(canvas, xremote_app_context_get_exit_str(app_ctx));
 }
 }
 
 
 static void xremote_navigation_view_process(XRemoteView* view, InputEvent* event)
 static void xremote_navigation_view_process(XRemoteView* view, InputEvent* event)
@@ -29,6 +36,8 @@ static void xremote_navigation_view_process(XRemoteView* view, InputEvent* event
         xremote_view_get_view(view),
         xremote_view_get_view(view),
         XRemoteViewModel* model,
         XRemoteViewModel* model,
         {
         {
+            model->context = xremote_view_get_app_context(view);
+
             if (event->type == InputTypePress)
             if (event->type == InputTypePress)
             {
             {
                 if (event->key == InputKeyUp)
                 if (event->key == InputKeyUp)
@@ -79,17 +88,38 @@ static bool xremote_navigation_view_input_callback(InputEvent* event, void* cont
 {
 {
     furi_assert(context);
     furi_assert(context);
     XRemoteView* view = (XRemoteView*)context;
     XRemoteView* view = (XRemoteView*)context;
+    XRemoteAppContext* app_ctx = xremote_view_get_app_context(view);
+    XRemoteAppExit exit = app_ctx->app_settings->exit_behavior;
 
 
-    if (event->type == InputTypeLong &&
-        event->key == InputKeyBack) return false;
+    if (event->key == InputKeyBack &&
+        event->type == InputTypeShort &&
+        exit == XRemoteAppExitPress) return false;
+    else if (event->key == InputKeyBack &&
+        event->type == InputTypeLong &&
+        exit == XRemoteAppExitHold) return false;
 
 
     xremote_navigation_view_process(view, event);
     xremote_navigation_view_process(view, event);
     return true;
     return true;
 }
 }
 
 
-XRemoteView* xremote_navigation_view_alloc(NotificationApp* notifications)
+XRemoteView* xremote_navigation_view_alloc(void* app_ctx)
 {
 {
-    return xremote_view_alloc(notifications,
+    XRemoteView *view = xremote_view_alloc(app_ctx,
         xremote_navigation_view_input_callback,
         xremote_navigation_view_input_callback,
         xremote_navigation_view_draw_callback);
         xremote_navigation_view_draw_callback);
+
+    with_view_model(
+        xremote_view_get_view(view),
+        XRemoteViewModel* model,
+        {
+            model->context = xremote_view_get_app_context(view);
+            model->up_pressed = false;
+            model->down_pressed = false;
+            model->left_pressed = false;
+            model->right_pressed = false;
+            model->back_pressed = false;
+            model->ok_pressed = false;
+        }, true);
+
+    return view;
 }
 }

+ 1 - 1
views/xremote_navigation_view.h

@@ -10,4 +10,4 @@
 
 
 #include "xremote_common_view.h"
 #include "xremote_common_view.h"
 
 
-XRemoteView* xremote_navigation_view_alloc(NotificationApp* notifications);
+XRemoteView* xremote_navigation_view_alloc(void* app_ctx);

+ 41 - 6
views/xremote_player_view.c

@@ -7,11 +7,13 @@
  */
  */
 
 
 #include "xremote_player_view.h"
 #include "xremote_player_view.h"
+#include "../xremote_app.h"
 
 
 static void xremote_player_view_draw_callback(Canvas* canvas, void* context)
 static void xremote_player_view_draw_callback(Canvas* canvas, void* context)
 {
 {
     furi_assert(context);
     furi_assert(context);
     XRemoteViewModel* model = context;
     XRemoteViewModel* model = context;
+    XRemoteAppContext *app_ctx = model->context;
 
 
     xremote_canvas_draw_header(canvas, "Playback");
     xremote_canvas_draw_header(canvas, "Playback");
     xremote_canvas_draw_button(canvas, model->up_pressed, 23, 30, XRemoteIconJumpForward);
     xremote_canvas_draw_button(canvas, model->up_pressed, 23, 30, XRemoteIconJumpForward);
@@ -19,8 +21,18 @@ static void xremote_player_view_draw_callback(Canvas* canvas, void* context)
     xremote_canvas_draw_button(canvas, model->ok_pressed, 23, 51, XRemoteIconPlayPause);
     xremote_canvas_draw_button(canvas, model->ok_pressed, 23, 51, XRemoteIconPlayPause);
     xremote_canvas_draw_button(canvas, model->left_pressed, 2, 51, XRemoteIconFastBackward);
     xremote_canvas_draw_button(canvas, model->left_pressed, 2, 51, XRemoteIconFastBackward);
     xremote_canvas_draw_button(canvas, model->right_pressed, 44, 51, XRemoteIconFastForward);
     xremote_canvas_draw_button(canvas, model->right_pressed, 44, 51, XRemoteIconFastForward);
-    xremote_canvas_draw_button(canvas, model->back_pressed, 2, 95, XRemoteIconStop);
-    xremote_canvas_draw_exit_footer(canvas, "Hold to exit");
+
+    if (app_ctx->app_settings->exit_behavior == XRemoteAppExitHold)
+    {
+        xremote_canvas_draw_button(canvas, model->back_pressed, 2, 95, XRemoteIconStop);
+    }
+    else
+    {
+        xremote_canvas_draw_button_wide(canvas, model->back_pressed, 2, 95, "Hold", XRemoteIconStop);
+        xremote_canvas_draw_icon(canvas, 50, 102, XRemoteIconBack);
+    }
+
+    xremote_canvas_draw_exit_footer(canvas, xremote_app_context_get_exit_str(app_ctx));
 }
 }
 
 
 static void xremote_player_view_process(XRemoteView* view, InputEvent* event)
 static void xremote_player_view_process(XRemoteView* view, InputEvent* event)
@@ -29,6 +41,8 @@ static void xremote_player_view_process(XRemoteView* view, InputEvent* event)
         xremote_view_get_view(view),
         xremote_view_get_view(view),
         XRemoteViewModel* model,
         XRemoteViewModel* model,
         {
         {
+            model->context = xremote_view_get_app_context(view);
+
             if (event->type == InputTypePress)
             if (event->type == InputTypePress)
             {
             {
                 if (event->key == InputKeyUp)
                 if (event->key == InputKeyUp)
@@ -79,17 +93,38 @@ static bool xremote_player_view_input_callback(InputEvent* event, void* context)
 {
 {
     furi_assert(context);
     furi_assert(context);
     XRemoteView* view = (XRemoteView*)context;
     XRemoteView* view = (XRemoteView*)context;
+    XRemoteAppContext* app_ctx = xremote_view_get_app_context(view);
+    XRemoteAppExit exit = app_ctx->app_settings->exit_behavior;
 
 
-    if (event->type == InputTypeLong &&
-        event->key == InputKeyBack) return false;
+    if (event->key == InputKeyBack &&
+        event->type == InputTypeShort &&
+        exit == XRemoteAppExitPress) return false;
+    else if (event->key == InputKeyBack &&
+        event->type == InputTypeLong &&
+        exit == XRemoteAppExitHold) return false;
 
 
     xremote_player_view_process(view, event);
     xremote_player_view_process(view, event);
     return true;
     return true;
 }
 }
 
 
-XRemoteView* xremote_player_view_alloc(NotificationApp* notifications)
+XRemoteView* xremote_player_view_alloc(void* app_ctx)
 {
 {
-    return xremote_view_alloc(notifications,
+    XRemoteView *view = xremote_view_alloc(app_ctx,
         xremote_player_view_input_callback,
         xremote_player_view_input_callback,
         xremote_player_view_draw_callback);
         xremote_player_view_draw_callback);
+
+    with_view_model(
+        xremote_view_get_view(view),
+        XRemoteViewModel* model,
+        {
+            model->context = xremote_view_get_app_context(view);
+            model->up_pressed = false;
+            model->down_pressed = false;
+            model->left_pressed = false;
+            model->right_pressed = false;
+            model->back_pressed = false;
+            model->ok_pressed = false;
+        }, true);
+
+    return view;
 }
 }

+ 1 - 1
views/xremote_player_view.h

@@ -10,4 +10,4 @@
 
 
 #include "xremote_common_view.h"
 #include "xremote_common_view.h"
 
 
-XRemoteView* xremote_player_view_alloc(NotificationApp* notifications);
+XRemoteView* xremote_player_view_alloc(void* app_ctx);

+ 15 - 10
xremote_app.c

@@ -16,6 +16,7 @@ XRemoteAppSettings* xremote_app_settings_alloc()
 {
 {
     XRemoteAppSettings* settings = malloc(sizeof(XRemoteAppSettings));
     XRemoteAppSettings* settings = malloc(sizeof(XRemoteAppSettings));
     settings->orientation = ViewOrientationHorizontal;
     settings->orientation = ViewOrientationHorizontal;
+    settings->exit_behavior = XRemoteAppExitHold;
     settings->repeat_count = 1;
     settings->repeat_count = 1;
     return settings;
     return settings;
 }
 }
@@ -41,9 +42,9 @@ bool xremote_app_settings_store(XRemoteAppSettings* settings)
         if (!flipper_format_write_comment_cstr(ff, "")) break;
         if (!flipper_format_write_comment_cstr(ff, "")) break;
 
 
         /* Write actual configuration to the settings file */
         /* Write actual configuration to the settings file */
-        uint32_t orientation = settings->orientation;
-        if (!flipper_format_write_uint32(ff, "orientation", &orientation, 1)) break;
-        if (!flipper_format_write_uint32(ff, "repeat", &settings->repeat_count, 1)) break;
+        if (!flipper_format_write_uint32(ff, "orientation", (uint32_t*)&settings->orientation, 1)) break;
+        if (!flipper_format_write_uint32(ff, "repeat", (uint32_t*)&settings->repeat_count, 1)) break;
+        if (!flipper_format_write_uint32(ff, "exit", (uint32_t*)&settings->exit_behavior, 1)) break;
 
 
         success = true;
         success = true;
     } while(false);
     } while(false);
@@ -61,7 +62,7 @@ bool xremote_app_settings_load(XRemoteAppSettings* settings)
     FuriString* header = furi_string_alloc();
     FuriString* header = furi_string_alloc();
 
 
     FURI_LOG_I(TAG, "load config file: \'%s\'", XREMOTE_APP_SETTINGS);
     FURI_LOG_I(TAG, "load config file: \'%s\'", XREMOTE_APP_SETTINGS);
-    uint32_t version, orientation, repeat = 0;
+    uint32_t version = 0;
     bool success = false;
     bool success = false;
 
 
     do {
     do {
@@ -71,11 +72,9 @@ bool xremote_app_settings_load(XRemoteAppSettings* settings)
         if (!furi_string_equal(header, "XRemote settings file") || (version != 1)) break;
         if (!furi_string_equal(header, "XRemote settings file") || (version != 1)) break;
 
 
         /* Parse config data from the buffer */
         /* Parse config data from the buffer */
-        if (!flipper_format_read_uint32(ff, "orientation", &orientation, 1)) break;
-        if (!flipper_format_read_uint32(ff, "repeat", &repeat, 1)) break;
-
-        settings->orientation = orientation;
-        settings->repeat_count = repeat;
+        if (!flipper_format_read_uint32(ff, "orientation", (uint32_t*)&settings->orientation, 1)) break;
+        if (!flipper_format_read_uint32(ff, "repeat", (uint32_t*)&settings->repeat_count, 1)) break;
+        if (!flipper_format_read_uint32(ff, "exit", (uint32_t*)&settings->exit_behavior, 1)) break;
 
 
         success = true;
         success = true;
     } while(false);
     } while(false);
@@ -118,6 +117,12 @@ void xremote_app_context_free(XRemoteAppContext* ctx)
     free(ctx);
     free(ctx);
 }
 }
 
 
+const char* xremote_app_context_get_exit_str(XRemoteAppContext* ctx)
+{
+    XRemoteAppExit exit_behavior = ctx->app_settings->exit_behavior;
+    return exit_behavior == XRemoteAppExitHold ? "Hold to exit" : "Press to exit";
+}
+
 void xremote_app_view_alloc(XRemoteApp *app, uint32_t view_id, XRemoteViewAllocator allocator)
 void xremote_app_view_alloc(XRemoteApp *app, uint32_t view_id, XRemoteViewAllocator allocator)
 {
 {
     furi_assert(app);
     furi_assert(app);
@@ -129,7 +134,7 @@ void xremote_app_view_alloc(XRemoteApp *app, uint32_t view_id, XRemoteViewAlloca
     xremote_app_view_free(app);
     xremote_app_view_free(app);
     app->view_id = view_id;
     app->view_id = view_id;
 
 
-    app->view_ctx = allocator(app->app_ctx->notifications);
+    app->view_ctx = allocator(app->app_ctx);
     View* app_view = xremote_view_get_view(app->view_ctx);
     View* app_view = xremote_view_get_view(app->view_ctx);
 
 
     ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;
     ViewDispatcher* view_disp = app->app_ctx->view_dispatcher;

+ 11 - 4
xremote_app.h

@@ -29,14 +29,23 @@
 #define xremote_app_assert_void(cond) if (!cond) return
 #define xremote_app_assert_void(cond) if (!cond) return
 #define xremote_app_assert(cond, var) if (!cond) return var
 #define xremote_app_assert(cond, var) if (!cond) return var
 
 
+typedef enum {
+    XRemoteAppExitPress,
+    XRemoteAppExitHold
+} XRemoteAppExit;
+
 typedef struct {
 typedef struct {
     ViewOrientation orientation;
     ViewOrientation orientation;
+    XRemoteAppExit exit_behavior;
     uint32_t repeat_count;
     uint32_t repeat_count;
 } XRemoteAppSettings;
 } XRemoteAppSettings;
 
 
 XRemoteAppSettings* xremote_app_settings_alloc();
 XRemoteAppSettings* xremote_app_settings_alloc();
 void xremote_app_settings_free(XRemoteAppSettings* settings);
 void xremote_app_settings_free(XRemoteAppSettings* settings);
 
 
+bool xremote_app_settings_store(XRemoteAppSettings* settings);
+bool xremote_app_settings_load(XRemoteAppSettings* settings);
+
 typedef struct {
 typedef struct {
     XRemoteAppSettings* app_settings;
     XRemoteAppSettings* app_settings;
     NotificationApp* notifications;
     NotificationApp* notifications;
@@ -47,11 +56,9 @@ typedef struct {
 
 
 XRemoteAppContext* xremote_app_context_alloc(void* arg);
 XRemoteAppContext* xremote_app_context_alloc(void* arg);
 void xremote_app_context_free(XRemoteAppContext* ctx);
 void xremote_app_context_free(XRemoteAppContext* ctx);
+const char* xremote_app_context_get_exit_str(XRemoteAppContext* ctx);
 
 
-bool xremote_app_settings_store(XRemoteAppSettings* settings);
-bool xremote_app_settings_load(XRemoteAppSettings* settings);
-
-typedef XRemoteView* (*XRemoteViewAllocator)(NotificationApp* notifications);
+typedef XRemoteView* (*XRemoteViewAllocator)(void* app_ctx);
 typedef void (*XRemoteAppClearCallback)(void *context);
 typedef void (*XRemoteAppClearCallback)(void *context);
 
 
 typedef struct {
 typedef struct {

+ 60 - 4
xremote_settings.c

@@ -14,23 +14,50 @@ typedef struct {
 } XRemoteSettingsContext;
 } XRemoteSettingsContext;
 
 
 #define XREMOTE_ORIENTATION_TEXT_HORIZONTAL     "Horizontal"
 #define XREMOTE_ORIENTATION_TEXT_HORIZONTAL     "Horizontal"
-#define XREMOTE_ORIENTATION_INDEX_HORIZONTAL    0
-
 #define XREMOTE_ORIENTATION_TEXT_VERTICAL       "Vertical"
 #define XREMOTE_ORIENTATION_TEXT_VERTICAL       "Vertical"
-#define XREMOTE_ORIENTATION_INDEX_VERTICAL      1
-
 #define XREMOTE_ORIENTATION_TEXT                "Orientation"
 #define XREMOTE_ORIENTATION_TEXT                "Orientation"
+#define XREMOTE_ORIENTATION_INDEX_HORIZONTAL    0
+#define XREMOTE_ORIENTATION_INDEX_VERTICAL      1
 #define XREMOTE_ORIENTATION_MAX                 2
 #define XREMOTE_ORIENTATION_MAX                 2
 
 
+#define XREMOTE_EXIT_BEHAVIOR_TEXT_PRESS        "Press"
+#define XREMOTE_EXIT_BEHAVIOR_TEXT_HOLD         "Hold"
+#define XREMOTE_EXIT_BEHAVIOR_TEXT              "Exit App"
+#define XREMOTE_EXIT_BEHAVIOR_INDEX_PRESS       0
+#define XREMOTE_EXIT_BEHAVIOR_INDEX_HOLD        1
+#define XREMOTE_EXIT_BEHAVIOR_MAX               2
+
 #define XREMOTE_REPEAT_TEXT                     "IR Msg Repeat"
 #define XREMOTE_REPEAT_TEXT                     "IR Msg Repeat"
 #define XREMOTE_REPEAT_MAX                      128
 #define XREMOTE_REPEAT_MAX                      128
 
 
+
 static uint32_t xremote_settings_view_exit_callback(void* context)
 static uint32_t xremote_settings_view_exit_callback(void* context)
 {
 {
     UNUSED(context);
     UNUSED(context);
     return XRemoteViewSubmenu;
     return XRemoteViewSubmenu;
 }
 }
 
 
+static uint32_t xremote_settings_get_exit_index(XRemoteAppSettings* settings)
+{
+    return settings->exit_behavior == XRemoteAppExitPress ?
+        XREMOTE_EXIT_BEHAVIOR_INDEX_PRESS :
+        XREMOTE_EXIT_BEHAVIOR_INDEX_HOLD;
+}
+
+static const char* xremote_settings_get_exit_str(XRemoteAppSettings* settings)
+{
+    return settings->exit_behavior == XRemoteAppExitPress ?
+        XREMOTE_EXIT_BEHAVIOR_TEXT_PRESS :
+        XREMOTE_EXIT_BEHAVIOR_TEXT_HOLD;
+}
+
+static XRemoteAppExit xremote_settings_get_exit_behavior(uint8_t exit_behavior)
+{
+    return exit_behavior == XREMOTE_EXIT_BEHAVIOR_INDEX_PRESS ?
+        XRemoteAppExitPress :
+        XRemoteAppExitHold;
+}
+
 static uint32_t xremote_settings_get_orientation_index(XRemoteAppSettings* settings)
 static uint32_t xremote_settings_get_orientation_index(XRemoteAppSettings* settings)
 {
 {
     return settings->orientation == ViewOrientationHorizontal ?
     return settings->orientation == ViewOrientationHorizontal ?
@@ -78,6 +105,19 @@ static void infrared_settings_repeat_changed(VariableItem* item)
     xremote_app_settings_store(settings);
     xremote_app_settings_store(settings);
 }
 }
 
 
+static void infrared_settings_exit_changed(VariableItem* item)
+{
+    XRemoteSettingsContext* ctx = variable_item_get_context(item);
+    XRemoteAppSettings* settings = ctx->app_ctx->app_settings;
+
+    uint8_t exit = variable_item_get_current_value_index(item);
+    settings->exit_behavior = xremote_settings_get_exit_behavior(exit);
+    const char* exit_str = xremote_settings_get_exit_str(settings);
+
+    variable_item_set_current_value_text(item, exit_str);
+    xremote_app_settings_store(settings);
+}
+
 static XRemoteSettingsContext* xremote_settings_context_alloc(XRemoteAppContext* app_ctx)
 static XRemoteSettingsContext* xremote_settings_context_alloc(XRemoteAppContext* app_ctx)
 {
 {
     XRemoteSettingsContext *context = malloc(sizeof(XRemoteSettingsContext));
     XRemoteSettingsContext *context = malloc(sizeof(XRemoteSettingsContext));
@@ -121,6 +161,22 @@ static XRemoteSettingsContext* xremote_settings_context_alloc(XRemoteAppContext*
     variable_item_set_current_value_index(item, settings->repeat_count);
     variable_item_set_current_value_index(item, settings->repeat_count);
     variable_item_set_current_value_text(item, repeat_str);
     variable_item_set_current_value_text(item, repeat_str);
 
 
+    /* Add exit behavior to variable item list */
+    item = variable_item_list_add(
+        context->item_list,
+        XREMOTE_EXIT_BEHAVIOR_TEXT,
+        XREMOTE_EXIT_BEHAVIOR_MAX,
+        infrared_settings_exit_changed,
+        context);
+
+    /* Get exit behavior settings */
+    const char* exit_str = xremote_settings_get_exit_str(settings);
+    uint32_t exit_index = xremote_settings_get_exit_index(settings);
+
+    /* Set exit behavior item index and string */
+    variable_item_set_current_value_index(item, exit_index);
+    variable_item_set_current_value_text(item, exit_str);
+
     return context;
     return context;
 }
 }