diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index 1fdfc7c9a..2b8f2a271 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -161,8 +161,12 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context); static void browser_folder_open_cb(void* context, uint32_t item_cnt, int32_t file_idx, bool is_root); static void browser_list_load_cb(void* context, uint32_t list_load_offset); -static void - browser_list_item_cb(void* context, FuriString* item_path, uint32_t idx, bool is_folder, bool is_last); +static void browser_list_item_cb( + void* context, + FuriString* item_path, + uint32_t idx, + bool is_folder, + bool is_last); static void browser_long_load_cb(void* context); static void file_browser_scroll_timer_callback(void* context) { @@ -416,8 +420,12 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset) { BrowserItem_t_clear(&back_item); } -static void - browser_list_item_cb(void* context, FuriString* item_path, uint32_t idx, bool is_folder, bool is_last) { +static void browser_list_item_cb( + void* context, + FuriString* item_path, + uint32_t idx, + bool is_folder, + bool is_last) { furi_assert(context); FileBrowser* browser = (FileBrowser*)context; @@ -470,16 +478,21 @@ static void browser->view, FileBrowserModel * model, { - FuriString* selected = NULL; - if(model->item_idx > 0) { - selected = furi_string_alloc_set(items_array_get(model->items, model->item_idx)->path); - } - items_array_sort(model->items); - if(selected) { - for(uint32_t i = 0; i < model->item_cnt; i++) { - if(!furi_string_cmp(items_array_get(model->items, i)->path, selected)) { - model->item_idx = i; - break; + if(model->item_cnt < 430) { + FuriString* selected = NULL; + if(model->item_idx > 0) { + selected = furi_string_alloc_set( + items_array_get(model->items, model->item_idx)->path); + } + + items_array_sort(model->items); + + if(selected != NULL) { + for(uint32_t i = 0; i < model->item_cnt; i++) { + if(!furi_string_cmp(items_array_get(model->items, i)->path, selected)) { + model->item_idx = i; + break; + } } } } diff --git a/applications/services/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c index 5955d8714..faf307d55 100644 --- a/applications/services/gui/modules/file_browser_worker.c +++ b/applications/services/gui/modules/file_browser_worker.c @@ -189,6 +189,87 @@ static bool browser_folder_init( return state; } +static bool browser_folder_load_chunked( + BrowserWorker* browser, + FuriString* path, + uint32_t offset, + uint32_t count) { + FileInfo file_info; + + Storage* storage = furi_record_open(RECORD_STORAGE); + File* directory = storage_file_alloc(storage); + + char name_temp[FILE_NAME_LEN_MAX]; + FuriString* name_str; + name_str = furi_string_alloc(); + + uint32_t items_cnt = 0; + + do { + if(!storage_dir_open(directory, furi_string_get_cstr(path))) { + break; + } + + items_cnt = 0; + while(items_cnt < offset) { + if(!storage_dir_read(directory, &file_info, name_temp, FILE_NAME_LEN_MAX)) { + break; + } + if(storage_file_get_error(directory) == FSE_OK) { + furi_string_set(name_str, name_temp); + if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { + items_cnt++; + } + } else { + break; + } + } + if(items_cnt != offset) { + break; + } + + if(browser->list_load_cb) { + browser->list_load_cb(browser->cb_ctx, offset); + } + + items_cnt = 0; + while(items_cnt < count) { + if(!storage_dir_read(directory, &file_info, name_temp, FILE_NAME_LEN_MAX)) { + break; + } + if(storage_file_get_error(directory) == FSE_OK) { + furi_string_set(name_str, name_temp); + if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { + furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp); + if(browser->list_item_cb) { + browser->list_item_cb( + browser->cb_ctx, + name_str, + items_cnt, + (file_info.flags & FSF_DIRECTORY), + false); + } + items_cnt++; + } + } else { + break; + } + } + if(browser->list_item_cb) { + browser->list_item_cb(browser->cb_ctx, NULL, 0, false, true); + } + } while(0); + + furi_string_free(name_str); + + storage_dir_close(directory); + storage_file_free(directory); + + furi_record_close(RECORD_STORAGE); + + return (items_cnt == count); +} + static bool browser_folder_load(BrowserWorker* browser, FuriString* path, uint32_t offset, uint32_t count) { FileInfo file_info; @@ -246,7 +327,11 @@ static bool furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp); if(browser->list_item_cb) { browser->list_item_cb( - browser->cb_ctx, name_str, items_cnt, (file_info.flags & FSF_DIRECTORY), false); + browser->cb_ctx, + name_str, + items_cnt, + (file_info.flags & FSF_DIRECTORY), + false); } items_cnt++; } @@ -361,7 +446,12 @@ static int32_t browser_worker(void* context) { if(flags & WorkerEvtLoad) { FURI_LOG_D( TAG, "Load offset: %lu cnt: %lu", browser->load_offset, browser->load_count); - browser_folder_load(browser, path, browser->load_offset, browser->load_count); + if(items_cnt > 430) { + browser_folder_load_chunked( + browser, path, browser->load_offset, browser->load_count); + } else { + browser_folder_load(browser, path, browser->load_offset, browser->load_count); + } } if(flags & WorkerEvtStop) {