From 769c53b6da48a59d0e0d43a2ddc3f6221f9ccfe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Tue, 29 Nov 2022 03:59:24 +0900 Subject: [PATCH] [FL-2977] Gui: better navigation in file browser dialog (#2014) * Gui: proper navigation in file browser dialog * Trim file name from start path * File list loading fix * File list offset fix Co-authored-by: nminaylov Co-authored-by: Sergey Gavrilov --- .../main/archive/helpers/archive_browser.c | 3 +-- .../main/archive/helpers/archive_browser.h | 2 +- .../services/gui/modules/file_browser.c | 22 ++++++++++++++++--- .../gui/modules/file_browser_worker.c | 17 ++++++++++++++ .../gui/modules/file_browser_worker.h | 2 ++ firmware/targets/f7/api_symbols.csv | 1 + 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index 9689454b..149b3908 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -265,8 +265,7 @@ void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) { offset_new = model->item_idx - FILE_LIST_BUF_LEN / 4 * 1; } if(offset_new > 0) { - offset_new = - CLAMP(offset_new, (int32_t)model->item_cnt - FILE_LIST_BUF_LEN, 0); + offset_new = CLAMP(offset_new, (int32_t)model->item_cnt, 0); } else { offset_new = 0; } diff --git a/applications/main/archive/helpers/archive_browser.h b/applications/main/archive/helpers/archive_browser.h index 1a7e01f5..09ffea1f 100644 --- a/applications/main/archive/helpers/archive_browser.h +++ b/applications/main/archive/helpers/archive_browser.h @@ -5,7 +5,7 @@ #define TAB_RIGHT InputKeyRight // Default tab switch direction #define TAB_DEFAULT ArchiveTabFavorites // Start tab -#define FILE_LIST_BUF_LEN 100 +#define FILE_LIST_BUF_LEN 50 static const char* tab_default_paths[] = { [ArchiveTabFavorites] = "/app:favorites", diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index 60e78b01..203be23e 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -232,7 +232,10 @@ static bool browser_is_item_in_array(FileBrowserModel* model, uint32_t idx) { static bool browser_is_list_load_required(FileBrowserModel* model) { size_t array_size = items_array_size(model->items); - uint32_t item_cnt = (model->is_root) ? model->item_cnt : model->item_cnt - 1; + if((array_size > 0) && (!model->is_root) && (model->array_offset == 0)) { + array_size--; + } + uint32_t item_cnt = (model->is_root) ? (model->item_cnt) : (model->item_cnt - 1); if((model->list_loading) || (array_size >= item_cnt)) { return false; @@ -524,7 +527,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { model->list_loading = true; int32_t load_offset = CLAMP( model->item_idx - ITEM_LIST_LEN_MAX / 4 * 3, - (int32_t)model->item_cnt - ITEM_LIST_LEN_MAX, + (int32_t)model->item_cnt, 0); file_browser_worker_load( browser->worker, load_offset, ITEM_LIST_LEN_MAX); @@ -535,7 +538,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { model->list_loading = true; int32_t load_offset = CLAMP( model->item_idx - ITEM_LIST_LEN_MAX / 4 * 1, - (int32_t)model->item_cnt - ITEM_LIST_LEN_MAX, + (int32_t)model->item_cnt, 0); file_browser_worker_load( browser->worker, load_offset, ITEM_LIST_LEN_MAX); @@ -590,6 +593,19 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { } consumed = true; } + } else if(event->key == InputKeyBack) { + if(event->type == InputTypeShort) { + bool is_root = false; + with_view_model( + browser->view, FileBrowserModel * model, { is_root = model->is_root; }, false); + + if(!is_root && !file_browser_worker_is_in_start_folder(browser->worker)) { + consumed = true; + if(!is_root) { + file_browser_worker_folder_exit(browser->worker); + } + } + } } return consumed; diff --git a/applications/services/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c index 34d83032..a85a14b7 100644 --- a/applications/services/gui/modules/file_browser_worker.c +++ b/applications/services/gui/modules/file_browser_worker.c @@ -35,6 +35,8 @@ struct BrowserWorker { FuriThread* thread; FuriString* filter_extension; + FuriString* path_start; + FuriString* path_current; FuriString* path_next; int32_t item_sel_idx; uint32_t load_offset; @@ -289,6 +291,7 @@ static int32_t browser_worker(void* context) { int32_t file_idx = 0; browser_folder_init(browser, path, filename, &items_cnt, &file_idx); + furi_string_set(browser->path_current, path); FURI_LOG_D( TAG, "Enter folder: %s items: %lu idx: %ld", @@ -311,6 +314,7 @@ static int32_t browser_worker(void* context) { // Pop previous selected item index from history array idx_last_array_pop_back(&file_idx, browser->idx_last); } + furi_string_set(browser->path_current, path); FURI_LOG_D( TAG, "Exit to: %s items: %lu idx: %ld", @@ -365,8 +369,14 @@ BrowserWorker* browser->filter_extension = furi_string_alloc_set(filter_ext); browser->skip_assets = skip_assets; + browser->path_start = furi_string_alloc_set(path); + browser->path_current = furi_string_alloc_set(path); browser->path_next = furi_string_alloc_set(path); + if(browser_path_is_file(browser->path_start)) { + browser_path_trim(browser->path_start); + } + browser->thread = furi_thread_alloc_ex("BrowserWorker", 2048, browser_worker, browser); furi_thread_start(browser->thread); @@ -382,6 +392,8 @@ void file_browser_worker_free(BrowserWorker* browser) { furi_string_free(browser->filter_extension); furi_string_free(browser->path_next); + furi_string_free(browser->path_current); + furi_string_free(browser->path_start); idx_last_array_clear(browser->idx_last); @@ -440,6 +452,11 @@ void file_browser_worker_folder_enter(BrowserWorker* browser, FuriString* path, furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderEnter); } +bool file_browser_worker_is_in_start_folder(BrowserWorker* browser) { + furi_assert(browser); + return (furi_string_cmp(browser->path_start, browser->path_current) == 0); +} + void file_browser_worker_folder_exit(BrowserWorker* browser) { furi_assert(browser); furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderExit); diff --git a/applications/services/gui/modules/file_browser_worker.h b/applications/services/gui/modules/file_browser_worker.h index 230bb5b4..2f815540 100644 --- a/applications/services/gui/modules/file_browser_worker.h +++ b/applications/services/gui/modules/file_browser_worker.h @@ -52,6 +52,8 @@ void file_browser_worker_set_config( void file_browser_worker_folder_enter(BrowserWorker* browser, FuriString* path, int32_t item_idx); +bool file_browser_worker_is_in_start_folder(BrowserWorker* browser); + void file_browser_worker_folder_exit(BrowserWorker* browser); void file_browser_worker_folder_refresh(BrowserWorker* browser, int32_t item_idx); diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index f3ed374b..17b36a2a 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -817,6 +817,7 @@ Function,+,file_browser_worker_folder_enter,void,"BrowserWorker*, FuriString*, i Function,+,file_browser_worker_folder_exit,void,BrowserWorker* Function,+,file_browser_worker_folder_refresh,void,"BrowserWorker*, int32_t" Function,+,file_browser_worker_free,void,BrowserWorker* +Function,+,file_browser_worker_is_in_start_folder,_Bool,BrowserWorker* Function,+,file_browser_worker_load,void,"BrowserWorker*, uint32_t, uint32_t" Function,+,file_browser_worker_set_callback_context,void,"BrowserWorker*, void*" Function,+,file_browser_worker_set_config,void,"BrowserWorker*, FuriString*, const char*, _Bool"