[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>
This commit is contained in:
		@@ -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;
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
		
		
			
  | 
		Reference in New Issue
	
	Block a user