From d5df0483a3a02a78dcddd76f7b5039c77c29e372 Mon Sep 17 00:00:00 2001 From: its your bedtime <23366927+itsyourbedtime@users.noreply.github.com> Date: Wed, 2 Jun 2021 15:51:05 +0300 Subject: [PATCH] [FL-1234] Keyboards redesign (#501) * text input: keyboard redesign,; input: tune repeat keypress timing; archive: fix max string width when scrollbar is shown * byte input: redesign * byte/text input: long press back to activate backspace added * archive: pass absolute path to app * format sources * better keyboard timings Co-authored-by: SG --- applications/archive/archive.c | 11 ++-- applications/archive/archive_views.c | 2 +- applications/gui/modules/byte_input.c | 44 ++++++++++++---- applications/gui/modules/text_input.c | 73 +++++++++++++++++++-------- applications/input/input_i.h | 4 +- 5 files changed, 96 insertions(+), 38 deletions(-) diff --git a/applications/archive/archive.c b/applications/archive/archive.c index 9408c636..11e7ab1e 100644 --- a/applications/archive/archive.c +++ b/applications/archive/archive.c @@ -130,7 +130,6 @@ static void set_file_type(ArchiveFile_t* file, FileInfo* file_info) { static bool archive_get_filenames(ArchiveApp* archive) { furi_assert(archive); - FS_Dir_Api* dir_api = &archive->fs_api->dir; ArchiveFile_t item; FileInfo file_info; @@ -169,7 +168,6 @@ static bool archive_get_filenames(ArchiveApp* archive) { files_array_push_back(model->files, item); ArchiveFile_t_clear(&item); } - } else { dir_api->close(&directory); string_clear(name); @@ -329,8 +327,15 @@ static void archive_file_menu_callback(ArchiveApp* archive) { switch(model->menu_idx) { case 0: if((selected->type != ArchiveFileTypeFolder && selected->type != ArchiveFileTypeUnknown)) { + string_t full_path; + string_init_set(full_path, archive->browser.path); + string_cat(full_path, "/"); + string_cat(full_path, selected->name); + archive_open_app( - archive, flipper_app_name[selected->type], string_get_cstr(selected->name)); + archive, flipper_app_name[selected->type], string_get_cstr(full_path)); + + string_clear(full_path); } break; case 1: diff --git a/applications/archive/archive_views.c b/applications/archive/archive_views.c index 2dd22190..0531b985 100644 --- a/applications/archive/archive_views.c +++ b/applications/archive/archive_views.c @@ -89,7 +89,7 @@ static void draw_list(Canvas* canvas, ArchiveViewModel* model) { string_set(str_buff, file->name); if(is_known_app(file->type)) trim_file_ext(str_buff); - elements_string_fit_width(canvas, str_buff, MAX_LEN_PX); + elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX); if(model->idx == idx) { archive_draw_frame(canvas, i, scrollbar); diff --git a/applications/gui/modules/byte_input.c b/applications/gui/modules/byte_input.c index eaa952ad..c3398e44 100644 --- a/applications/gui/modules/byte_input.c +++ b/applications/gui/modules/byte_input.c @@ -150,10 +150,13 @@ static char byte_input_get_nibble_text(uint8_t byte, bool high_nibble) { * @param model */ static void byte_input_draw_input(Canvas* canvas, ByteInputModel* model) { - const uint8_t text_x = 3; + const uint8_t text_x = 8; const uint8_t text_y = 25; - elements_slightly_rounded_frame(canvas, 1, 14, 126, 15); + elements_slightly_rounded_frame(canvas, 6, 14, 116, 15); + + canvas_draw_icon_name(canvas, 2, 19, I_ButtonLeftSmall_3x5); + canvas_draw_icon_name(canvas, 123, 19, I_ButtonRightSmall_3x5); for(uint8_t i = model->first_visible_byte; i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes); @@ -234,12 +237,15 @@ static void byte_input_draw_input(Canvas* canvas, ByteInputModel* model) { * @param model */ static void byte_input_draw_input_selected(Canvas* canvas, ByteInputModel* model) { - const uint8_t text_x = 3; + const uint8_t text_x = 7; const uint8_t text_y = 25; - canvas_draw_box(canvas, 0, 12, 128, 19); + canvas_draw_box(canvas, 0, 12, 127, 19); canvas_invert_color(canvas); - elements_slightly_rounded_frame(canvas, 1, 14, 126, 15); + + elements_slightly_rounded_frame(canvas, 6, 14, 115, 15); + canvas_draw_icon_name(canvas, 2, 19, I_ButtonLeftSmall_3x5); + canvas_draw_icon_name(canvas, 122, 19, I_ButtonRightSmall_3x5); for(uint8_t i = model->first_visible_byte; i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes); @@ -247,7 +253,7 @@ static void byte_input_draw_input_selected(Canvas* canvas, ByteInputModel* model uint8_t byte_position = i - model->first_visible_byte; if(i == model->selected_byte) { - canvas_draw_box(canvas, text_x + byte_position * 14, text_y - 9, 15, 11); + canvas_draw_box(canvas, text_x + 1 + byte_position * 14, text_y - 9, 13, 11); canvas_invert_color(canvas); canvas_draw_glyph( canvas, @@ -406,6 +412,17 @@ static void byte_input_call_changed_callback(ByteInputModel* model) { } } +/** + * @brief Clear selected byte + */ + +static void byte_input_clear_selected_byte(ByteInputModel* model) { + model->bytes[model->selected_byte] = 0; + model->selected_high_nibble = true; + byte_input_dec_selected_byte(model); + byte_input_call_changed_callback(model); +} + /** * @brief Handle up button * @@ -478,10 +495,7 @@ static void byte_input_handle_ok(ByteInputModel* model) { if(value == enter_symbol) { byte_input_call_input_callback(model); } else if(value == backspace_symbol) { - model->bytes[model->selected_byte] = 0; - model->selected_high_nibble = true; - byte_input_dec_selected_byte(model); - byte_input_call_changed_callback(model); + byte_input_clear_selected_byte(model); } else { byte_input_set_nibble( model->bytes, model->selected_byte, value, model->selected_high_nibble); @@ -647,6 +661,16 @@ static bool byte_input_view_input_callback(InputEvent* event, void* context) { } } + if((event->type == InputTypeLong || event->type == InputTypeRepeat) && + event->key == InputKeyBack) { + with_view_model( + byte_input->view, (ByteInputModel * model) { + byte_input_clear_selected_byte(model); + return true; + }); + consumed = true; + } + return consumed; } diff --git a/applications/gui/modules/text_input.c b/applications/gui/modules/text_input.c index 44f5ab9c..2afe7368 100644 --- a/applications/gui/modules/text_input.c +++ b/applications/gui/modules/text_input.c @@ -42,10 +42,10 @@ static const TextInputKey keyboard_keys_row_1[] = { {'i', 64, 8}, {'o', 73, 8}, {'p', 82, 8}, - {'7', 91, 8}, - {'8', 100, 8}, - {'9', 109, 8}, - {'_', 118, 8}, + {'0', 91, 8}, + {'1', 100, 8}, + {'2', 110, 8}, + {'3', 120, 8}, }; static const TextInputKey keyboard_keys_row_2[] = { @@ -58,10 +58,10 @@ static const TextInputKey keyboard_keys_row_2[] = { {'j', 55, 20}, {'k', 64, 20}, {'l', 73, 20}, - {'4', 82, 20}, - {'5', 91, 20}, - {'6', 100, 20}, - {BACKSPACE_KEY, 110, 12}, + {BACKSPACE_KEY, 82, 12}, + {'4', 100, 20}, + {'5', 110, 20}, + {'6', 120, 20}, }; static const TextInputKey keyboard_keys_row_3[] = { @@ -72,11 +72,11 @@ static const TextInputKey keyboard_keys_row_3[] = { {'b', 37, 32}, {'n', 46, 32}, {'m', 55, 32}, - {'0', 64, 32}, - {'1', 73, 32}, - {'2', 82, 32}, - {'3', 91, 32}, - {ENTER_KEY, 102, 23}, + {'_', 64, 32}, + {ENTER_KEY, 74, 23}, + {'7', 100, 32}, + {'8', 110, 32}, + {'9', 120, 32}, }; static uint8_t get_row_size(uint8_t row_index) { @@ -127,24 +127,41 @@ static const char char_to_uppercase(const char letter) { return (letter - 0x20); } +static void text_input_backspace_cb(TextInputModel* model) { + uint8_t text_length = strlen(model->text); + if(text_length > 0) { + model->text[text_length - 1] = 0; + } +} + static void text_input_view_draw_callback(Canvas* canvas, void* _model) { TextInputModel* model = _model; uint8_t text_length = strlen(model->text); - uint8_t needed_string_width = canvas_width(canvas) - 4 - 7 - 4; + uint8_t needed_string_width = canvas_width(canvas) - 8; + uint8_t start_pos = 4; + char* text = model->text; canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); canvas_draw_str(canvas, 2, 8, model->header); - elements_slightly_rounded_frame(canvas, 1, 12, 122, 15); + elements_slightly_rounded_frame(canvas, 1, 12, 126, 15); + + if(canvas_string_width(canvas, text) > needed_string_width) { + canvas_draw_str(canvas, start_pos, 22, "..."); + start_pos += 6; + needed_string_width -= 8; + } while(text != 0 && canvas_string_width(canvas, text) > needed_string_width) { text++; } - canvas_draw_str(canvas, 4, 22, text); - canvas_draw_str(canvas, 4 + canvas_string_width(canvas, text) + 1, 22, "|"); + canvas_draw_str(canvas, start_pos, 22, text); + + canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 1, 22, "|"); + canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 2, 22, "|"); canvas_set_font(canvas, FontKeyboard); @@ -220,6 +237,9 @@ static void text_input_handle_up(TextInput* text_input) { text_input->view, (TextInputModel * model) { if(model->selected_row > 0) { model->selected_row--; + if(model->selected_column > get_row_size(model->selected_row) - 5) { + model->selected_column = model->selected_column + 1; + } } return true; }); @@ -230,8 +250,8 @@ static void text_input_handle_down(TextInput* text_input) { text_input->view, (TextInputModel * model) { if(model->selected_row < keyboard_row_count - 1) { model->selected_row++; - if(model->selected_column > get_row_size(model->selected_row) - 1) { - model->selected_column = get_row_size(model->selected_row) - 1; + if(model->selected_column > get_row_size(model->selected_row) - 4) { + model->selected_column = model->selected_column - 1; } } return true; @@ -273,9 +293,7 @@ static void text_input_handle_ok(TextInput* text_input) { model->callback(model->callback_context, model->text); } } else if(selected == BACKSPACE_KEY) { - if(text_length > 0) { - model->text[text_length - 1] = 0; - } + text_input_backspace_cb(model); } else if(text_length < model->max_text_length) { if(text_length == 0 && char_is_lowercase(selected)) { selected = char_to_uppercase(selected); @@ -319,6 +337,17 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) { } } + if((event->type == InputTypeLong || event->type == InputTypeRepeat) && + event->key == InputKeyBack) { + with_view_model( + text_input->view, (TextInputModel * model) { + text_input_backspace_cb(model); + return true; + }); + + consumed = true; + } + return consumed; } diff --git a/applications/input/input_i.h b/applications/input/input_i.h index eb2df35a..a3262fc4 100644 --- a/applications/input/input_i.h +++ b/applications/input/input_i.h @@ -12,8 +12,8 @@ #include #define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2) -#define INPUT_PRESS_TICKS 200 -#define INPUT_LONG_PRESS_COUNTS 4 +#define INPUT_PRESS_TICKS 150 +#define INPUT_LONG_PRESS_COUNTS 2 #define INPUT_THREAD_FLAG_ISR 0x00000001 /* Input pin state */