diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index b2f0a1804..9cb66a5e5 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -65,7 +65,13 @@ static void archive_add_file_item(browser, is_folder, furi_string_get_cstr(item_path)); } else { with_view_model( - browser->view, ArchiveBrowserViewModel * model, { model->list_loading = false; }, true); + browser->view, + ArchiveBrowserViewModel * model, + { + files_array_sort(model->files); + model->list_loading = false; + }, + true); } } @@ -140,7 +146,7 @@ void archive_update_focus(ArchiveBrowserView* browser, const char* target) { archive_get_items(browser, furi_string_get_cstr(browser->path)); if(!archive_file_get_array_size(browser) && archive_is_home(browser)) { - archive_switch_tab(browser, TAB_RIGHT); + archive_switch_tab(browser, TAB_LEFT); } else { with_view_model( browser->view, @@ -207,7 +213,7 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) { false); if((items_cnt == 0) && (archive_is_home(browser))) { - archive_switch_tab(browser, TAB_RIGHT); + archive_switch_tab(browser, TAB_LEFT); } archive_update_offset(browser); @@ -459,6 +465,7 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { } if(tab == ArchiveTabInternal && !furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) continue; break; + } browser->is_root = true; archive_set_tab(browser, tab); diff --git a/applications/main/archive/helpers/archive_browser.h b/applications/main/archive/helpers/archive_browser.h index f25ed48c8..43a9a651a 100644 --- a/applications/main/archive/helpers/archive_browser.h +++ b/applications/main/archive/helpers/archive_browser.h @@ -3,7 +3,7 @@ #include "../archive_i.h" #include -#define TAB_RIGHT InputKeyRight // Default tab switch direction +#define TAB_LEFT InputKeyLeft // Default tab switch direction #define TAB_DEFAULT ArchiveTabFavorites // Start tab #define FILE_LIST_BUF_LEN 50 diff --git a/applications/main/archive/helpers/archive_files.h b/applications/main/archive/helpers/archive_files.h index d2cd93a66..a9c33c9f6 100644 --- a/applications/main/archive/helpers/archive_files.h +++ b/applications/main/archive/helpers/archive_files.h @@ -2,8 +2,11 @@ #include #include +#include +#include #include #include "toolbox/path.h" +#include "../../../settings/xtreme_settings/xtreme_settings.h" #define FAP_MANIFEST_MAX_ICON_SIZE 32 @@ -81,13 +84,31 @@ static void ArchiveFile_t_clear(ArchiveFile_t* obj) { furi_string_free(obj->custom_name); } -ARRAY_DEF( - files_array, - ArchiveFile_t, - (INIT(API_2(ArchiveFile_t_init)), - SET(API_6(ArchiveFile_t_set)), - INIT_SET(API_6(ArchiveFile_t_init_set)), - CLEAR(API_2(ArchiveFile_t_clear)))) +static int ArchiveFile_t_cmp(const ArchiveFile_t* a, const ArchiveFile_t* b) { + if(!XTREME_SETTINGS()->sort_ignore_dirs) { + if(a->type == ArchiveFileTypeFolder && b->type != ArchiveFileTypeFolder) { + return -1; + } + if(a->type != ArchiveFileTypeFolder && b->type == ArchiveFileTypeFolder) { + return 1; + } + } + + return furi_string_cmpi(a->path, b->path); +} + +#define M_OPL_ArchiveFile_t() \ + (INIT(API_2(ArchiveFile_t_init)), \ + SET(API_6(ArchiveFile_t_set)), \ + INIT_SET(API_6(ArchiveFile_t_init_set)), \ + CLEAR(API_2(ArchiveFile_t_clear)), \ + CMP(API_6(ArchiveFile_t_cmp)), \ + SWAP(M_SWAP_DEFAULT), \ + EQUAL(API_6(M_EQUAL_DEFAULT))) + +ARRAY_DEF(files_array, ArchiveFile_t) + +ALGO_DEF(files_array, ARRAY_OPLIST(files_array, M_OPL_ArchiveFile_t())) void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder, bool is_app); bool archive_get_items(void* context, const char* path); diff --git a/applications/main/archive/views/archive_browser_view.c b/applications/main/archive/views/archive_browser_view.c index 1e993c9f0..26ed17d75 100644 --- a/applications/main/archive/views/archive_browser_view.c +++ b/applications/main/archive/views/archive_browser_view.c @@ -589,4 +589,4 @@ void browser_free(ArchiveBrowserView* browser) { view_free(browser->view); free(browser); -} +} \ No newline at end of file diff --git a/applications/main/archive/views/archive_browser_view.h b/applications/main/archive/views/archive_browser_view.h index 923de1ff4..6e6582405 100644 --- a/applications/main/archive/views/archive_browser_view.h +++ b/applications/main/archive/views/archive_browser_view.h @@ -2,7 +2,6 @@ #include "../helpers/archive_files.h" #include "../helpers/archive_favorites.h" -#include "../helpers/archive_menu.h" #include #include @@ -10,7 +9,10 @@ #include #include #include -#include +#include "../helpers/archive_files.h" +#include "../helpers/archive_menu.h" +#include "../helpers/archive_favorites.h" +#include "gui/modules/file_browser_worker.h" #define MAX_LEN_PX 110 #define MAX_NAME_LEN 255 diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index d12a00ba5..03b3b0eab 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -11,6 +11,8 @@ #include #include #include +#include "m-string.h" +#include "m-algo.h" #include #define LIST_ITEMS 5u @@ -77,13 +79,38 @@ static void BrowserItem_t_clear(BrowserItem_t* obj) { } } -ARRAY_DEF( - items_array, - BrowserItem_t, - (INIT(API_2(BrowserItem_t_init)), - SET(API_6(BrowserItem_t_set)), - INIT_SET(API_6(BrowserItem_t_init_set)), - CLEAR(API_2(BrowserItem_t_clear)))) +static int BrowserItem_t_cmp(const BrowserItem_t* a, const BrowserItem_t* b) { + // Back indicator comes before everything, then folders, then all other files. + if(a->type == BrowserItemTypeBack) { + return -1; + } + if(b->type == BrowserItemTypeBack) { + return 1; + } + if(!XTREME_SETTINGS()->sort_ignore_dirs) { + if(a->type == BrowserItemTypeFolder && b->type != BrowserItemTypeFolder) { + return -1; + } + if(a->type != BrowserItemTypeFolder && b->type == BrowserItemTypeFolder) { + return 1; + } + } + + return furi_string_cmpi(a->path, b->path); +} + +#define M_OPL_BrowserItem_t() \ + (INIT(API_2(BrowserItem_t_init)), \ + SET(API_6(BrowserItem_t_set)), \ + INIT_SET(API_6(BrowserItem_t_init_set)), \ + CLEAR(API_2(BrowserItem_t_clear)), \ + CMP(API_6(BrowserItem_t_cmp)), \ + SWAP(M_SWAP_DEFAULT), \ + EQUAL(API_6(M_EQUAL_DEFAULT))) + +ARRAY_DEF(items_array, BrowserItem_t) + +ALGO_DEF(items_array, ARRAY_OPLIST(items_array, M_OPL_BrowserItem_t())) struct FileBrowser { View* view; @@ -438,7 +465,13 @@ static void } } else { with_view_model( - browser->view, FileBrowserModel * model, { model->list_loading = false; }, true); + browser->view, + FileBrowserModel * model, + { + items_array_sort(model->items); + model->list_loading = false; + }, + true); } } diff --git a/applications/services/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c index 80c4f4c43..4453b6d9f 100644 --- a/applications/services/gui/modules/file_browser_worker.c +++ b/applications/services/gui/modules/file_browser_worker.c @@ -15,6 +15,8 @@ #define TAG "BrowserWorker" #define ASSETS_DIR "assets" +#define BADUSB_LAYOUTS_DIR "layouts" +#define SUBGHZ_TEMP_DIR "tmp_history" #define BROWSER_ROOT STORAGE_ANY_PATH_PREFIX #define FILE_NAME_LEN_MAX 256 #define LONG_LOAD_THRESHOLD 100 @@ -90,7 +92,9 @@ static bool browser_filter_by_name(BrowserWorker* browser, FuriString* name, boo if(is_folder) { // Skip assets folders (if enabled) if(browser->skip_assets) { - return ((furi_string_cmp_str(name, ASSETS_DIR) == 0) ? (false) : (true)); + return ((furi_string_cmp_str(name, ASSETS_DIR) == 0) ? (false) : (true)) && + ((furi_string_cmp_str(name, BADUSB_LAYOUTS_DIR) == 0) ? (false) : (true)) && + ((furi_string_cmp_str(name, SUBGHZ_TEMP_DIR) == 0) ? (false) : (true)); } else { return true; } @@ -202,55 +206,58 @@ static bool uint32_t items_cnt = 0; + bool ret = false; 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; - } + // 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; + // } + // FLIPPER DEVS MOMENT + // this used to load the file list in chunks, and then sort it... + // so while scrolling, it loads more files and sorts them... + // chances are, the new files are higher in the sorted list... + // so the files keep shifting around while scrolling... + // now this does something intelligent and loads all in one go. + // might take a few milliseconds longer, but atleast it works :kekw: + UNUSED(offset); + UNUSED(count); if(browser->list_load_cb) { - browser->list_load_cb(browser->cb_ctx, offset); + browser->list_load_cb(browser->cb_ctx, 0); } - - 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, (file_info.flags & FSF_DIRECTORY), false); - } - items_cnt++; + while(storage_dir_read(directory, &file_info, name_temp, FILE_NAME_LEN_MAX) && + 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, (file_info.flags & FSF_DIRECTORY), false); } - } else { - break; + items_cnt++; } } if(browser->list_item_cb) { browser->list_item_cb(browser->cb_ctx, NULL, false, true); } + ret = true; } while(0); furi_string_free(name_str); @@ -260,7 +267,7 @@ static bool furi_record_close(RECORD_STORAGE); - return (items_cnt == count); + return ret; } static int32_t browser_worker(void* context) {