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

[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 <nm29719@gmail.com>
Co-authored-by: Sergey Gavrilov <who.just.the.doctor@gmail.com>
あく 3 лет назад
Родитель
Сommit
769c53b6da

+ 1 - 2
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;
                 }

+ 1 - 1
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",

+ 19 - 3
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;

+ 17 - 0
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);

+ 2 - 0
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);

+ 1 - 0
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"