From 8ca076c2382d1b926e7844e12f132f9a6b541207 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 17 Jan 2023 17:14:54 +0100 Subject: [PATCH] Refactoring of code to show/hide the keyboard. --- app.h | 3 +++ ui.c | 33 +++++++++++++++++++++++++++++++++ view_info.c | 8 +++----- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/app.h b/app.h index a7162faf6a2..7397bea8fbe 100644 --- a/app.h +++ b/app.h @@ -218,6 +218,9 @@ int get_current_subview(ProtoViewApp *app); void show_available_subviews(Canvas *canvas, ProtoViewApp *app, int last_subview); bool process_subview_updown(ProtoViewApp *app, InputEvent input, int last_subview); void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color); +void show_keyboard(ProtoViewApp *app, char *buffer, uint32_t buflen, + void (*done_callback)(void*)); +void dismiss_keyboard(ProtoViewApp *app); /* crc.c */ uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly); diff --git a/ui.c b/ui.c index 169d01ac13c..eceb82dc014 100644 --- a/ui.c +++ b/ui.c @@ -3,6 +3,11 @@ #include "app.h" +/* =========================== Subview handling ================================ + * Note that these are not the Flipper subviews, but the subview system + * implemented inside ProtoView. + * ========================================================================== */ + /* Return the ID of the currently selected subview, of the current * view. */ int get_current_subview(ProtoViewApp *app) { @@ -41,6 +46,34 @@ bool process_subview_updown(ProtoViewApp *app, InputEvent input, int last_subvie return false; } +/* ============================= Text input ==================================== + * Normally we just use our own private UI widgets. However for the text input + * widget, that is quite complex, visualizes a keyboard and must be standardized + * for user coherent experience, we use the one provided by the Flipper + * framework. The following two functions allow to show the keyboard to get + * text and later dismiss it. + * ========================================================================== */ + +/* Show the keyboard, take the user input and store it into the specified + * 'buffer' of 'buflen' total bytes. When the user is done, the done_callback + * is called passing the application context to it. Such callback needs + * to do whatever it wants with the input buffer and dismissi the keyboard + * calling: dismiss_keyboard(app); */ +void show_keyboard(ProtoViewApp *app, char *buffer, uint32_t buflen, + void (*done_callback)(void*)) +{ + app->show_text_input = true; + app->text_input_buffer = buffer; + app->text_input_buffer_len = buflen; + app->text_input_done_callback = done_callback; +} + +void dismiss_keyboard(ProtoViewApp *app) { + view_dispatcher_stop(app->view_dispatcher); +} + +/* =========================== Canvas extensions ============================ */ + void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color) { struct { diff --git a/view_info.c b/view_info.c index 98cc8aab258..332b72f0bf4 100644 --- a/view_info.c +++ b/view_info.c @@ -97,7 +97,7 @@ void text_input_done_callback(void* context) { ProtoViewApp *app = context; InfoViewPrivData *privdata = app->view_privdata; free(privdata->filename); - view_dispatcher_stop(app->view_dispatcher); + dismiss_keyboard(app); } /* Handle input for the info view. */ @@ -121,10 +121,8 @@ void process_input_info(ProtoViewApp *app, InputEvent input) { privdata->signal_display_start_row--; } else if (input.type == InputTypePress && input.key == InputKeyOk) { privdata->filename = malloc(SAVE_FILENAME_LEN); - app->show_text_input = true; - app->text_input_buffer = privdata->filename; - app->text_input_buffer_len = SAVE_FILENAME_LEN; - app->text_input_done_callback = text_input_done_callback; + show_keyboard(app, privdata->filename, SAVE_FILENAME_LEN, + text_input_done_callback); } } }