From 49a16070e34ad2ccbb90288741444ca1453e2c3c Mon Sep 17 00:00:00 2001 From: r3df0xx Date: Fri, 27 May 2022 17:29:42 +0300 Subject: [PATCH] fff --- .../file_browser_test/file_browser_app.c | 99 ---- .../file_browser_test/file_browser_app_i.h | 32 -- .../scenes/file_browser_scene.c | 30 - .../scenes/file_browser_scene.h | 29 - .../scenes/file_browser_scene_browser.c | 45 -- .../scenes/file_browser_scene_config.h | 3 - .../scenes/file_browser_scene_result.c | 36 -- .../scenes/file_browser_scene_start.c | 44 -- applications/gui/modules/file_browser.c | 532 ------------------ applications/gui/modules/file_browser.h | 39 -- .../gui/modules/file_browser_worker.c | 420 -------------- .../gui/modules/file_browser_worker.h | 57 -- 12 files changed, 1366 deletions(-) delete mode 100644 applications/debug_tools/file_browser_test/file_browser_app.c delete mode 100644 applications/debug_tools/file_browser_test/file_browser_app_i.h delete mode 100644 applications/debug_tools/file_browser_test/scenes/file_browser_scene.c delete mode 100644 applications/debug_tools/file_browser_test/scenes/file_browser_scene.h delete mode 100644 applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c delete mode 100644 applications/debug_tools/file_browser_test/scenes/file_browser_scene_config.h delete mode 100644 applications/debug_tools/file_browser_test/scenes/file_browser_scene_result.c delete mode 100644 applications/debug_tools/file_browser_test/scenes/file_browser_scene_start.c delete mode 100644 applications/gui/modules/file_browser.c delete mode 100644 applications/gui/modules/file_browser.h delete mode 100644 applications/gui/modules/file_browser_worker.c delete mode 100644 applications/gui/modules/file_browser_worker.h diff --git a/applications/debug_tools/file_browser_test/file_browser_app.c b/applications/debug_tools/file_browser_test/file_browser_app.c deleted file mode 100644 index a408f5cde..000000000 --- a/applications/debug_tools/file_browser_test/file_browser_app.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "assets_icons.h" -#include "file_browser_app_i.h" -#include "gui/modules/file_browser.h" -#include "m-string.h" -#include -#include -#include -#include - -static bool file_browser_app_custom_event_callback(void* context, uint32_t event) { - furi_assert(context); - FileBrowserApp* app = context; - return scene_manager_handle_custom_event(app->scene_manager, event); -} - -static bool file_browser_app_back_event_callback(void* context) { - furi_assert(context); - FileBrowserApp* app = context; - return scene_manager_handle_back_event(app->scene_manager); -} - -static void file_browser_app_tick_event_callback(void* context) { - furi_assert(context); - FileBrowserApp* app = context; - scene_manager_handle_tick_event(app->scene_manager); -} - -FileBrowserApp* file_browser_app_alloc(char* arg) { - UNUSED(arg); - FileBrowserApp* app = malloc(sizeof(FileBrowserApp)); - - app->gui = furi_record_open("gui"); - app->dialogs = furi_record_open("dialogs"); - - app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - - app->scene_manager = scene_manager_alloc(&file_browser_scene_handlers, app); - - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_set_tick_event_callback( - app->view_dispatcher, file_browser_app_tick_event_callback, 500); - view_dispatcher_set_custom_event_callback( - app->view_dispatcher, file_browser_app_custom_event_callback); - view_dispatcher_set_navigation_event_callback( - app->view_dispatcher, file_browser_app_back_event_callback); - - app->widget = widget_alloc(); - - string_init(app->file_path); - app->file_browser = file_browser_alloc(&(app->file_path)); - file_browser_configure(app->file_browser, "*", true, &I_badusb_10px, true); - - view_dispatcher_add_view( - app->view_dispatcher, FileBrowserAppViewStart, widget_get_view(app->widget)); - view_dispatcher_add_view( - app->view_dispatcher, FileBrowserAppViewResult, widget_get_view(app->widget)); - view_dispatcher_add_view( - app->view_dispatcher, FileBrowserAppViewBrowser, file_browser_get_view(app->file_browser)); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - scene_manager_next_scene(app->scene_manager, FileBrowserSceneStart); - - return app; -} - -void file_browser_app_free(FileBrowserApp* app) { - furi_assert(app); - - // Views - view_dispatcher_remove_view(app->view_dispatcher, FileBrowserAppViewStart); - view_dispatcher_remove_view(app->view_dispatcher, FileBrowserAppViewResult); - view_dispatcher_remove_view(app->view_dispatcher, FileBrowserAppViewBrowser); - widget_free(app->widget); - file_browser_free(app->file_browser); - - // View dispatcher - view_dispatcher_free(app->view_dispatcher); - scene_manager_free(app->scene_manager); - - // Close records - furi_record_close("gui"); - furi_record_close("notification"); - furi_record_close("dialogs"); - - string_clear(app->file_path); - - free(app); -} - -int32_t file_browser_app(void* p) { - FileBrowserApp* file_browser_app = file_browser_app_alloc((char*)p); - - view_dispatcher_run(file_browser_app->view_dispatcher); - - file_browser_app_free(file_browser_app); - return 0; -} diff --git a/applications/debug_tools/file_browser_test/file_browser_app_i.h b/applications/debug_tools/file_browser_test/file_browser_app_i.h deleted file mode 100644 index 6e8412c9b..000000000 --- a/applications/debug_tools/file_browser_test/file_browser_app_i.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "scenes/file_browser_scene.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct FileBrowserApp FileBrowserApp; - -struct FileBrowserApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - DialogsApp* dialogs; - Widget* widget; - FileBrowser* file_browser; - - string_t file_path; -}; - -typedef enum { - FileBrowserAppViewStart, - FileBrowserAppViewBrowser, - FileBrowserAppViewResult, -} FileBrowserAppView; diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene.c b/applications/debug_tools/file_browser_test/scenes/file_browser_scene.c deleted file mode 100644 index 72a6e84d7..000000000 --- a/applications/debug_tools/file_browser_test/scenes/file_browser_scene.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "file_browser_scene.h" - -// Generate scene on_enter handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, -void (*const file_browser_scene_on_enter_handlers[])(void*) = { -#include "file_browser_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_event handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, -bool (*const file_browser_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { -#include "file_browser_scene_config.h" -}; -#undef ADD_SCENE - -// Generate scene on_exit handlers array -#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, -void (*const file_browser_scene_on_exit_handlers[])(void* context) = { -#include "file_browser_scene_config.h" -}; -#undef ADD_SCENE - -// Initialize scene handlers configuration structure -const SceneManagerHandlers file_browser_scene_handlers = { - .on_enter_handlers = file_browser_scene_on_enter_handlers, - .on_event_handlers = file_browser_scene_on_event_handlers, - .on_exit_handlers = file_browser_scene_on_exit_handlers, - .scene_num = FileBrowserSceneNum, -}; diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene.h b/applications/debug_tools/file_browser_test/scenes/file_browser_scene.h deleted file mode 100644 index d690fca9f..000000000 --- a/applications/debug_tools/file_browser_test/scenes/file_browser_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// Generate scene id and total number -#define ADD_SCENE(prefix, name, id) FileBrowserScene##id, -typedef enum { -#include "file_browser_scene_config.h" - FileBrowserSceneNum, -} FileBrowserScene; -#undef ADD_SCENE - -extern const SceneManagerHandlers file_browser_scene_handlers; - -// Generate scene on_enter handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); -#include "file_browser_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_event handlers declaration -#define ADD_SCENE(prefix, name, id) \ - bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); -#include "file_browser_scene_config.h" -#undef ADD_SCENE - -// Generate scene on_exit handlers declaration -#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); -#include "file_browser_scene_config.h" -#undef ADD_SCENE diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c b/applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c deleted file mode 100644 index 9c570cec0..000000000 --- a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "../file_browser_app_i.h" -#include "furi/check.h" -#include "furi/log.h" -#include "furi_hal.h" -#include "m-string.h" - -#define DEFAULT_PATH "/" -#define EXTENSION "*" - -bool file_browser_scene_browser_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - FileBrowserApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - scene_manager_next_scene(app->scene_manager, FileBrowserSceneResult); - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - } - return consumed; -} - -static void file_browser_callback(void* context, bool state) { - FileBrowserApp* app = context; - furi_assert(app); - view_dispatcher_send_custom_event(app->view_dispatcher, SceneManagerEventTypeCustom); - - UNUSED(state); -} - -void file_browser_scene_browser_on_enter(void* context) { - FileBrowserApp* app = context; - - file_browser_set_callback(app->file_browser, file_browser_callback, app); - - file_browser_start(app->file_browser, app->file_path); - - view_dispatcher_switch_to_view(app->view_dispatcher, FileBrowserAppViewBrowser); -} - -void file_browser_scene_browser_on_exit(void* context) { - FileBrowserApp* app = context; - - file_browser_stop(app->file_browser); -} diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_config.h b/applications/debug_tools/file_browser_test/scenes/file_browser_scene_config.h deleted file mode 100644 index 6597df3aa..000000000 --- a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_config.h +++ /dev/null @@ -1,3 +0,0 @@ -ADD_SCENE(file_browser, start, Start) -ADD_SCENE(file_browser, browser, Browser) -ADD_SCENE(file_browser, result, Result) diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_result.c b/applications/debug_tools/file_browser_test/scenes/file_browser_scene_result.c deleted file mode 100644 index 53576cef4..000000000 --- a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_result.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "../file_browser_app_i.h" -#include "furi_hal.h" -#include "m-string.h" - -void file_browser_scene_result_ok_callback(InputType type, void* context) { - furi_assert(context); - FileBrowserApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, type); -} - -bool file_browser_scene_result_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - //FileBrowserApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - } - return consumed; -} - -void file_browser_scene_result_on_enter(void* context) { - FileBrowserApp* app = context; - - widget_add_string_multiline_element( - app->widget, 64, 10, AlignCenter, AlignTop, FontSecondary, string_get_cstr(app->file_path)); - - view_dispatcher_switch_to_view(app->view_dispatcher, FileBrowserAppViewResult); -} - -void file_browser_scene_result_on_exit(void* context) { - UNUSED(context); - FileBrowserApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_start.c b/applications/debug_tools/file_browser_test/scenes/file_browser_scene_start.c deleted file mode 100644 index bb71e83df..000000000 --- a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_start.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "../file_browser_app_i.h" -#include "furi_hal.h" -#include "gui/modules/widget_elements/widget_element_i.h" - -static void - file_browser_scene_start_ok_callback(GuiButtonType result, InputType type, void* context) { - UNUSED(result); - furi_assert(context); - FileBrowserApp* app = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(app->view_dispatcher, type); - } -} - -bool file_browser_scene_start_on_event(void* context, SceneManagerEvent event) { - FileBrowserApp* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - string_set_str(app->file_path, "/any/badusb/demo_windows.txt"); - scene_manager_next_scene(app->scene_manager, FileBrowserSceneBrowser); - consumed = true; - } else if(event.type == SceneManagerEventTypeTick) { - } - return consumed; -} - -void file_browser_scene_start_on_enter(void* context) { - FileBrowserApp* app = context; - - widget_add_string_multiline_element( - app->widget, 64, 20, AlignCenter, AlignTop, FontSecondary, "Press OK to start"); - - widget_add_button_element( - app->widget, GuiButtonTypeCenter, "Ok", file_browser_scene_start_ok_callback, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, FileBrowserAppViewStart); -} - -void file_browser_scene_start_on_exit(void* context) { - UNUSED(context); - FileBrowserApp* app = context; - widget_reset(app->widget); -} diff --git a/applications/gui/modules/file_browser.c b/applications/gui/modules/file_browser.c deleted file mode 100644 index 919750962..000000000 --- a/applications/gui/modules/file_browser.c +++ /dev/null @@ -1,532 +0,0 @@ -#include "file_browser.h" -#include "assets_icons.h" -#include "cmsis_os2.h" -#include "file_browser_worker.h" -#include "furi/check.h" -#include "furi/common_defines.h" -#include "furi/log.h" -#include "furi_hal_resources.h" -#include "m-string.h" -#include -#include -#include - -#define LIST_ITEMS 5u -#define MAX_LEN_PX 110 -#define FRAME_HEIGHT 12 -#define Y_OFFSET 3 - -#define ITEM_LIST_LEN_MAX 100 - -typedef enum { - BrowserItemTypeLoading, - BrowserItemTypeBack, - BrowserItemTypeFolder, - BrowserItemTypeFile, -} BrowserItemType; - -typedef struct { - string_t path; - BrowserItemType type; -} BrowserItem_t; - -static void BrowserItem_t_init(BrowserItem_t* obj) { - obj->type = BrowserItemTypeLoading; - string_init(obj->path); -} - -static void BrowserItem_t_init_set(BrowserItem_t* obj, const BrowserItem_t* src) { - obj->type = src->type; - string_init_set(obj->path, src->path); -} - -static void BrowserItem_t_set(BrowserItem_t* obj, const BrowserItem_t* src) { - obj->type = src->type; - string_set(obj->path, src->path); -} - -static void BrowserItem_t_clear(BrowserItem_t* obj) { - string_clear(obj->path); -} - -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)))) - -struct FileBrowser { - View* view; - BrowserWorker* worker; - char* ext_filter; - bool skip_assets; - - FileBrowserCallback callback; - void* context; - - string_t* result_path; -}; - -typedef struct { - items_array_t items; - - bool is_root; - bool folder_loading; - bool list_loading; - uint32_t item_cnt; - int32_t item_idx; - int32_t array_offset; - int32_t list_offset; - - const Icon* file_icon; - bool hide_ext; -} FileBrowserModel; - -static const Icon* BrowserItemIcons[] = { - [BrowserItemTypeLoading] = &I_loading_10px, - [BrowserItemTypeBack] = &I_back_10px, - [BrowserItemTypeFolder] = &I_dir_10px, - [BrowserItemTypeFile] = &I_unknown_10px, -}; - -static void file_browser_view_draw_callback(Canvas* canvas, void* _model); -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, string_t item_path, bool is_folder, bool is_last); -static void browser_long_load_cb(void* context); - -FileBrowser* file_browser_alloc(string_t* result_path) { - furi_assert(result_path); - FileBrowser* browser = malloc(sizeof(FileBrowser)); - browser->view = view_alloc(); - view_allocate_model(browser->view, ViewModelTypeLocking, sizeof(FileBrowserModel)); - view_set_context(browser->view, browser); - view_set_draw_callback(browser->view, file_browser_view_draw_callback); - view_set_input_callback(browser->view, file_browser_view_input_callback); - - browser->result_path = result_path; - - with_view_model( - browser->view, (FileBrowserModel * model) { - items_array_init(model->items); - return false; - }); - - return browser; -} - -void file_browser_free(FileBrowser* browser) { - furi_assert(browser); - - with_view_model( - browser->view, (FileBrowserModel * model) { - items_array_clear(model->items); - return false; - }); - - view_free(browser->view); - free(browser); -} - -View* file_browser_get_view(FileBrowser* browser) { - furi_assert(browser); - return browser->view; -} - -void file_browser_configure( - FileBrowser* browser, - char* extension, - bool skip_assets, - const Icon* file_icon, - bool hide_ext) { - furi_assert(browser); - - browser->ext_filter = extension; - browser->skip_assets = skip_assets; - - with_view_model( - browser->view, (FileBrowserModel * model) { - model->file_icon = file_icon; - model->hide_ext = hide_ext; - return false; - }); -} - -void file_browser_start(FileBrowser* browser, string_t path) { - furi_assert(browser); - browser->worker = file_browser_worker_alloc(path, browser->ext_filter, browser->skip_assets); - file_browser_worker_set_callback_context(browser->worker, browser); - file_browser_worker_set_folder_callback(browser->worker, browser_folder_open_cb); - file_browser_worker_set_list_callback(browser->worker, browser_list_load_cb); - file_browser_worker_set_item_callback(browser->worker, browser_list_item_cb); - file_browser_worker_set_long_load_callback(browser->worker, browser_long_load_cb); -} - -void file_browser_stop(FileBrowser* browser) { - furi_assert(browser); - file_browser_worker_free(browser->worker); - with_view_model( - browser->view, (FileBrowserModel * model) { - items_array_reset(model->items); - model->item_cnt = 0; - model->item_idx = 0; - model->array_offset = 0; - model->list_offset = 0; - return false; - }); -} - -void file_browser_set_callback(FileBrowser* browser, FileBrowserCallback callback, void* context) { - browser->context = context; - browser->callback = callback; -} - -static bool browser_is_item_in_array(FileBrowserModel* model, uint32_t idx) { - size_t array_size = items_array_size(model->items); - - if((idx >= (uint32_t)model->array_offset + array_size) || - (idx < (uint32_t)model->array_offset)) { - return false; - } - return true; -} - -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((model->list_loading) || (array_size >= item_cnt)) { - return false; - } - - if((model->array_offset > 0) && - (model->item_idx < (model->array_offset + ITEM_LIST_LEN_MAX / 4))) { - return true; - } - - if(((model->array_offset + array_size) < item_cnt) && - (model->item_idx > (int32_t)(model->array_offset + array_size - ITEM_LIST_LEN_MAX / 4))) { - return true; - } - - return false; -} - -static void browser_update_offset(FileBrowser* browser) { - furi_assert(browser); - - with_view_model( - browser->view, (FileBrowserModel * model) { - uint16_t bounds = model->item_cnt > (LIST_ITEMS - 1) ? 2 : model->item_cnt; - - if((model->item_cnt > (LIST_ITEMS - 1)) && - (model->item_idx >= ((int32_t)model->item_cnt - 1))) { - model->list_offset = model->item_idx - (LIST_ITEMS - 1); - } else if(model->list_offset < model->item_idx - bounds) { - model->list_offset = CLAMP( - model->item_idx - (int32_t)(LIST_ITEMS - 2), - (int32_t)model->item_cnt - bounds, - 0); - } else if(model->list_offset > model->item_idx - bounds) { - model->list_offset = - CLAMP(model->item_idx - 1, (int32_t)model->item_cnt - bounds, 0); - } - - return false; - }); -} - -static void - browser_folder_open_cb(void* context, uint32_t item_cnt, int32_t file_idx, bool is_root) { - furi_assert(context); - FileBrowser* browser = (FileBrowser*)context; - - int32_t load_offset = 0; - - with_view_model( - browser->view, (FileBrowserModel * model) { - if(is_root) { - model->item_cnt = item_cnt; - model->item_idx = (file_idx > 0) ? file_idx : 0; - load_offset = - CLAMP(model->item_idx - ITEM_LIST_LEN_MAX / 2, (int32_t)model->item_cnt, 0); - } else { - model->item_cnt = item_cnt + 1; - model->item_idx = file_idx + 1; - load_offset = CLAMP( - model->item_idx - ITEM_LIST_LEN_MAX / 2 - 1, (int32_t)model->item_cnt - 1, 0); - } - model->array_offset = 0; - model->list_offset = 0; - model->is_root = is_root; - model->list_loading = true; - model->folder_loading = false; - return true; - }); - browser_update_offset(browser); - - file_browser_worker_load(browser->worker, load_offset, ITEM_LIST_LEN_MAX); -} - -static void browser_list_load_cb(void* context, uint32_t list_load_offset) { - furi_assert(context); - FileBrowser* browser = (FileBrowser*)context; - - BrowserItem_t back_item; - BrowserItem_t_init(&back_item); - back_item.type = BrowserItemTypeBack; - - with_view_model( - browser->view, (FileBrowserModel * model) { - items_array_reset(model->items); - model->array_offset = list_load_offset; - if(!model->is_root) { - if(list_load_offset == 0) { - items_array_push_back(model->items, back_item); - } else { - model->array_offset += 1; - } - } - return false; - }); - - BrowserItem_t_clear(&back_item); -} - -static void browser_list_item_cb(void* context, string_t item_path, bool is_folder, bool is_last) { - furi_assert(context); - FileBrowser* browser = (FileBrowser*)context; - - BrowserItem_t item; - - if(!is_last) { - BrowserItem_t_init(&item); - string_set(item.path, item_path); - item.type = (is_folder) ? BrowserItemTypeFolder : BrowserItemTypeFile; - - with_view_model( - browser->view, (FileBrowserModel * model) { - items_array_push_back(model->items, item); - return false; - }); - BrowserItem_t_clear(&item); - } else { - with_view_model( - browser->view, (FileBrowserModel * model) { - model->list_loading = false; - return true; - }); - } -} - -static void browser_long_load_cb(void* context) { - furi_assert(context); - FileBrowser* browser = (FileBrowser*)context; - - with_view_model( - browser->view, (FileBrowserModel * model) { - model->folder_loading = true; - return true; - }); -} - -static void browser_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box( - canvas, 0, Y_OFFSET + idx * FRAME_HEIGHT, (scrollbar ? 122 : 127), FRAME_HEIGHT); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_dot(canvas, 0, Y_OFFSET + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 1, Y_OFFSET + idx * FRAME_HEIGHT); - canvas_draw_dot(canvas, 0, (Y_OFFSET + idx * FRAME_HEIGHT) + 1); - - canvas_draw_dot(canvas, 0, (Y_OFFSET + idx * FRAME_HEIGHT) + (FRAME_HEIGHT - 1)); - canvas_draw_dot(canvas, scrollbar ? 121 : 126, Y_OFFSET + idx * FRAME_HEIGHT); - canvas_draw_dot( - canvas, scrollbar ? 121 : 126, (Y_OFFSET + idx * FRAME_HEIGHT) + (FRAME_HEIGHT - 1)); -} - -static void browser_draw_loading(Canvas* canvas, FileBrowserModel* model) { - uint8_t width = 49; - uint8_t height = 47; - uint8_t x = 128 / 2 - width / 2; - uint8_t y = 64 / 2 - height / 2; - - UNUSED(model); - - elements_bold_rounded_frame(canvas, x, y, width, height); - - canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, x + 7, y + 13, "Loading..."); - - canvas_draw_icon(canvas, x + 13, y + 19, &A_Loading_24); -} - -static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { - uint32_t array_size = items_array_size(model->items); - bool show_scrollbar = model->item_cnt > LIST_ITEMS; - - string_t filename; - string_init(filename); - - for(uint32_t i = 0; i < MIN(model->item_cnt, LIST_ITEMS); i++) { - int32_t idx = CLAMP((uint32_t)(i + model->list_offset), model->item_cnt, 0u); - - BrowserItemType item_type = BrowserItemTypeLoading; - - if(browser_is_item_in_array(model, idx)) { - BrowserItem_t* item = items_array_get( - model->items, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0)); - item_type = item->type; - file_browser_worker_get_filename( - item->path, filename, (model->hide_ext) && (item_type == BrowserItemTypeFile)); - } else { - string_set_str(filename, "---"); - } - - if(item_type == BrowserItemTypeBack) { - string_set_str(filename, ". ."); - } - - elements_string_fit_width( - canvas, filename, (show_scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX)); - - if(model->item_idx == idx) { - browser_draw_frame(canvas, i, show_scrollbar); - } else { - canvas_set_color(canvas, ColorBlack); - } - - if((item_type == BrowserItemTypeFile) && (model->file_icon)) { - canvas_draw_icon(canvas, 2, Y_OFFSET + 1 + i * FRAME_HEIGHT, model->file_icon); - } else if(BrowserItemIcons[item_type] != NULL) { - canvas_draw_icon( - canvas, 2, Y_OFFSET + 1 + i * FRAME_HEIGHT, BrowserItemIcons[item_type]); - } - canvas_draw_str(canvas, 15, Y_OFFSET + 9 + i * FRAME_HEIGHT, string_get_cstr(filename)); - } - - if(show_scrollbar) { - elements_scrollbar_pos( - canvas, - 126, - Y_OFFSET, - canvas_height(canvas) - Y_OFFSET, - model->item_idx, - model->item_cnt); - } - - string_clear(filename); -} - -static void file_browser_view_draw_callback(Canvas* canvas, void* _model) { - FileBrowserModel* model = _model; - - if(model->folder_loading) { - browser_draw_loading(canvas, model); - } else { - browser_draw_list(canvas, model); - } -} - -static bool file_browser_view_input_callback(InputEvent* event, void* context) { - FileBrowser* browser = context; - furi_assert(browser); - bool consumed = false; - bool is_loading = false; - - with_view_model( - browser->view, (FileBrowserModel * model) { - is_loading = model->folder_loading; - return false; - }); - - if(is_loading) { - return false; - } else if(event->key == InputKeyUp || event->key == InputKeyDown) { - if(event->type == InputTypeShort || event->type == InputTypeRepeat) { - with_view_model( - browser->view, (FileBrowserModel * model) { - if(event->key == InputKeyUp) { - model->item_idx = - ((model->item_idx - 1) + model->item_cnt) % model->item_cnt; - if(browser_is_list_load_required(model)) { - 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, - 0); - file_browser_worker_load( - browser->worker, load_offset, ITEM_LIST_LEN_MAX); - } - } else if(event->key == InputKeyDown) { - model->item_idx = (model->item_idx + 1) % model->item_cnt; - if(browser_is_list_load_required(model)) { - 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, - 0); - file_browser_worker_load( - browser->worker, load_offset, ITEM_LIST_LEN_MAX); - } - } - return true; - }); - browser_update_offset(browser); - consumed = true; - } - } else if(event->key == InputKeyOk) { - if(event->type == InputTypeShort) { - BrowserItem_t* selected_item = NULL; - int32_t select_index = 0; - with_view_model( - browser->view, (FileBrowserModel * model) { - if(browser_is_item_in_array(model, model->item_idx)) { - selected_item = - items_array_get(model->items, model->item_idx - model->array_offset); - select_index = model->item_idx; - if((!model->is_root) && (select_index > 0)) { - select_index -= 1; - } - } - return false; - }); - - if(selected_item) { - if(selected_item->type == BrowserItemTypeBack) { - file_browser_worker_folder_exit(browser->worker); - } else if(selected_item->type == BrowserItemTypeFolder) { - file_browser_worker_folder_enter( - browser->worker, selected_item->path, select_index); - } else if(selected_item->type == BrowserItemTypeFile) { - string_set(*(browser->result_path), selected_item->path); - if(browser->callback) { - browser->callback(browser->context, true); - } - } - } - consumed = true; - } - } else if(event->key == InputKeyLeft) { - if(event->type == InputTypeShort) { - bool is_root = false; - with_view_model( - browser->view, (FileBrowserModel * model) { - is_root = model->is_root; - return false; - }); - if(!is_root) { - file_browser_worker_folder_exit(browser->worker); - } - consumed = true; - } - } - - return consumed; -} diff --git a/applications/gui/modules/file_browser.h b/applications/gui/modules/file_browser.h deleted file mode 100644 index b77c6e65c..000000000 --- a/applications/gui/modules/file_browser.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file file_browser.h - * GUI: FileBrowser view module API - */ - -#pragma once - -#include "m-string.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct FileBrowser FileBrowser; -typedef void (*FileBrowserCallback)(void* context, bool state); - -FileBrowser* file_browser_alloc(string_t* result_path); - -void file_browser_free(FileBrowser* browser); - -View* file_browser_get_view(FileBrowser* browser); - -void file_browser_configure( - FileBrowser* browser, - char* extension, - bool skip_assets, - const Icon* file_icon, - bool hide_ext); - -void file_browser_start(FileBrowser* browser, string_t path); - -void file_browser_stop(FileBrowser* browser); - -void file_browser_set_callback(FileBrowser* browser, FileBrowserCallback callback, void* context); - -#ifdef __cplusplus -} -#endif diff --git a/applications/gui/modules/file_browser_worker.c b/applications/gui/modules/file_browser_worker.c deleted file mode 100644 index 13fc97111..000000000 --- a/applications/gui/modules/file_browser_worker.c +++ /dev/null @@ -1,420 +0,0 @@ -#include "file_browser_worker.h" -#include "furi/check.h" -#include "furi/common_defines.h" -#include "m-string.h" -#include "storage/filesystem_api_defines.h" -#include -#include -#include -#include -#include - -#define TAG "BrowserWorker" - -#define ASSETS_DIR "assets" -#define BROWSER_ROOT "/any" -#define FILE_NAME_LEN_MAX 256 -#define LONG_LOAD_THRESHOLD 100 - -typedef enum { - WorkerEvtStop = (1 << 0), - WorkerEvtLoad = (1 << 1), - WorkerEvtFolderEnter = (1 << 2), - WorkerEvtFolderExit = (1 << 3), -} WorkerEvtFlags; - -#define WORKER_FLAGS_ALL \ - (WorkerEvtStop | WorkerEvtLoad | WorkerEvtFolderEnter | WorkerEvtFolderExit) - -ARRAY_DEF(idx_last_array, int32_t) - -struct BrowserWorker { - FuriThread* thread; - - string_t filter_extension; - string_t path_next; - int32_t item_sel_idx; - uint32_t load_offset; - uint32_t load_count; - bool skip_assets; - idx_last_array_t idx_last; - - void* cb_ctx; - BrowserWorkerFolderOpenCallback folder_cb; - BrowserWorkerListLoadCallback list_load_cb; - BrowserWorkerListItemCallback list_item_cb; - BrowserWorkerLongLoadCallback long_load_cb; -}; - -static bool browser_path_is_file(string_t path) { - bool state = false; - FileInfo file_info; - Storage* storage = furi_record_open("storage"); - if(storage_common_stat(storage, string_get_cstr(path), &file_info) == FSE_OK) { - if((file_info.flags & FSF_DIRECTORY) == 0) { - state = true; - } - } - furi_record_close("storage"); - return state; -} - -static bool browser_path_trim(string_t path) { - bool is_root = false; - size_t filename_start = string_search_rchar(path, '/'); - string_left(path, filename_start); - if((string_empty_p(path)) || (filename_start == STRING_FAILURE)) { - string_set_str(path, BROWSER_ROOT); - is_root = true; - } - return is_root; -} - -static bool browser_filter_by_name(BrowserWorker* browser, string_t name, bool is_folder) { - if(is_folder) { - // Skip assets folders (if enabled) - if(browser->skip_assets) { - return ((string_cmp_str(name, ASSETS_DIR) == 0) ? (false) : (true)); - } else { - return true; - } - } else { - // Filter files by extension - if((string_empty_p(browser->filter_extension)) || - (string_cmp_str(browser->filter_extension, "*") == 0)) { - return true; - } - if(string_end_with_string_p(name, browser->filter_extension)) { - return true; - } - } - return false; -} - -static bool browser_folder_check_and_switch(string_t path) { - FileInfo file_info; - Storage* storage = furi_record_open("storage"); - bool is_root = false; - while(1) { - // Check if folder is existing and navigate back if not - if(storage_common_stat(storage, string_get_cstr(path), &file_info) == FSE_OK) { - if(file_info.flags & FSF_DIRECTORY) { - break; - } - } - if(is_root) { - break; - } - is_root = browser_path_trim(path); - } - furi_record_close("storage"); - return is_root; -} - -static bool browser_folder_init( - BrowserWorker* browser, - string_t path, - string_t filename, - uint32_t* item_cnt, - int32_t* file_idx) { - bool state = false; - FileInfo file_info; - uint32_t total_files_cnt = 0; - - Storage* storage = furi_record_open("storage"); - File* directory = storage_file_alloc(storage); - - char name_temp[FILE_NAME_LEN_MAX]; - string_t name_str; - string_init(name_str); - - *item_cnt = 0; - *file_idx = -1; - - if(storage_dir_open(directory, string_get_cstr(path))) { - state = true; - while(1) { - if(!storage_dir_read(directory, &file_info, name_temp, FILE_NAME_LEN_MAX)) { - break; - } - if((storage_file_get_error(directory) == FSE_OK) && (name_temp[0] != '\0')) { - total_files_cnt++; - string_set_str(name_str, name_temp); - if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { - if(!string_empty_p(filename)) { - if(string_cmp(name_str, filename) == 0) { - *file_idx = *item_cnt; - } - } - (*item_cnt)++; - } - if(total_files_cnt == LONG_LOAD_THRESHOLD) { - if(browser->long_load_cb) { - browser->long_load_cb(browser->cb_ctx); - } - } - } - } - } - - string_clear(name_str); - - storage_dir_close(directory); - storage_file_free(directory); - - furi_record_close("storage"); - - return state; -} - -static bool - browser_folder_load(BrowserWorker* browser, string_t path, uint32_t offset, uint32_t count) { - FileInfo file_info; - - Storage* storage = furi_record_open("storage"); - File* directory = storage_file_alloc(storage); - - char name_temp[FILE_NAME_LEN_MAX]; - string_t name_str; - string_init(name_str); - - uint32_t items_cnt = 0; - - do { - if(!storage_dir_open(directory, 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) { - string_set_str(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) { - string_set_str(name_str, name_temp); - if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { - string_printf(name_str, "%s/%s", 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++; - } - } else { - break; - } - } - if(browser->list_item_cb) { - browser->list_item_cb(browser->cb_ctx, NULL, false, true); - } - } while(0); - - string_clear(name_str); - - storage_dir_close(directory); - storage_file_free(directory); - - furi_record_close("storage"); - - return (items_cnt == count); -} - -static int32_t browser_worker(void* context) { - BrowserWorker* browser = (BrowserWorker*)context; - furi_assert(browser); - FURI_LOG_D(TAG, "Start"); - - uint32_t items_cnt = 0; - string_t path; - string_init_set_str(path, BROWSER_ROOT); - browser->item_sel_idx = -1; - - // If start path is a path to the file - try finding index of this file in a folder - string_t filename; - string_init(filename); - if(browser_path_is_file(browser->path_next)) { - file_browser_worker_get_filename(browser->path_next, filename, false); - } - - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderEnter); - - while(1) { - uint32_t flags = osThreadFlagsWait(WORKER_FLAGS_ALL, osFlagsWaitAny, osWaitForever); - furi_assert((flags & osFlagsError) == 0); - - if(flags & WorkerEvtFolderEnter) { - string_set(path, browser->path_next); - bool is_root = browser_folder_check_and_switch(path); - - // Push previous selected item index to history array - idx_last_array_push_back(browser->idx_last, browser->item_sel_idx); - - int32_t file_idx = 0; - browser_folder_init(browser, path, filename, &items_cnt, &file_idx); - FURI_LOG_D( - TAG, - "Enter folder: %s items: %u idx: %d", - string_get_cstr(path), - items_cnt, - file_idx); - if(browser->folder_cb) { - browser->folder_cb(browser->cb_ctx, items_cnt, file_idx, is_root); - } - string_reset(filename); - } - - if(flags & WorkerEvtFolderExit) { - browser_path_trim(path); - bool is_root = browser_folder_check_and_switch(path); - - int32_t file_idx = 0; - browser_folder_init(browser, path, filename, &items_cnt, &file_idx); - if(idx_last_array_size(browser->idx_last) > 0) { - // Pop previous selected item index from history array - idx_last_array_pop_back(&file_idx, browser->idx_last); - } - FURI_LOG_D( - TAG, "Exit to: %s items: %u idx: %d", string_get_cstr(path), items_cnt, file_idx); - if(browser->folder_cb) { - browser->folder_cb(browser->cb_ctx, items_cnt, file_idx, is_root); - } - } - - if(flags & WorkerEvtLoad) { - FURI_LOG_D(TAG, "Load offset: %u cnt: %u", browser->load_offset, browser->load_count); - browser_folder_load(browser, path, browser->load_offset, browser->load_count); - } - - if(flags & WorkerEvtStop) { - break; - } - } - - string_clear(filename); - string_clear(path); - - FURI_LOG_D(TAG, "End"); - return 0; -} - -void file_browser_worker_get_filename(string_t path, string_t name, bool trim_ext) { - size_t filename_start = string_search_rchar(path, '/'); - if(filename_start > 0) { - filename_start++; - string_set_n(name, path, filename_start, string_size(path) - filename_start); - } - if(trim_ext) { - size_t dot = string_search_rchar(name, '.'); - if(dot > 0) { - string_left(name, dot); - } - } -} - -BrowserWorker* file_browser_worker_alloc(string_t path, char* filter_ext, bool skip_assets) { - BrowserWorker* browser = malloc(sizeof(BrowserWorker)); - - idx_last_array_init(browser->idx_last); - - string_init_set_str(browser->filter_extension, filter_ext); - browser->skip_assets = skip_assets; - string_init_set(browser->path_next, path); - - browser->thread = furi_thread_alloc(); - furi_thread_set_name(browser->thread, "BrowserWorker"); - furi_thread_set_stack_size(browser->thread, 2048); - furi_thread_set_context(browser->thread, browser); - furi_thread_set_callback(browser->thread, browser_worker); - furi_thread_start(browser->thread); - - return browser; -} - -void file_browser_worker_free(BrowserWorker* browser) { - furi_assert(browser); - - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtStop); - furi_thread_join(browser->thread); - furi_thread_free(browser->thread); - - string_clear(browser->filter_extension); - string_clear(browser->path_next); - - idx_last_array_clear(browser->idx_last); - - free(browser); -} - -void file_browser_worker_set_callback_context(BrowserWorker* browser, void* context) { - furi_assert(browser); - browser->cb_ctx = context; -} - -void file_browser_worker_set_folder_callback( - BrowserWorker* browser, - BrowserWorkerFolderOpenCallback cb) { - furi_assert(browser); - browser->folder_cb = cb; -} - -void file_browser_worker_set_list_callback( - BrowserWorker* browser, - BrowserWorkerListLoadCallback cb) { - furi_assert(browser); - browser->list_load_cb = cb; -} - -void file_browser_worker_set_item_callback( - BrowserWorker* browser, - BrowserWorkerListItemCallback cb) { - furi_assert(browser); - browser->list_item_cb = cb; -} - -void file_browser_worker_set_long_load_callback( - BrowserWorker* browser, - BrowserWorkerLongLoadCallback cb) { - furi_assert(browser); - browser->long_load_cb = cb; -} - -void file_browser_worker_folder_enter(BrowserWorker* browser, string_t path, int32_t item_idx) { - furi_assert(browser); - string_set(browser->path_next, path); - browser->item_sel_idx = item_idx; - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderEnter); -} - -void file_browser_worker_folder_exit(BrowserWorker* browser) { - furi_assert(browser); - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderExit); -} - -void file_browser_worker_load(BrowserWorker* browser, uint32_t offset, uint32_t count) { - furi_assert(browser); - browser->load_offset = offset; - browser->load_count = count; - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtLoad); -} diff --git a/applications/gui/modules/file_browser_worker.h b/applications/gui/modules/file_browser_worker.h deleted file mode 100644 index 821d5103f..000000000 --- a/applications/gui/modules/file_browser_worker.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "m-string.h" -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BrowserWorker BrowserWorker; -typedef void (*BrowserWorkerFolderOpenCallback)( - void* context, - uint32_t item_cnt, - int32_t file_idx, - bool is_root); -typedef void (*BrowserWorkerListLoadCallback)(void* context, uint32_t list_load_offset); -typedef void (*BrowserWorkerListItemCallback)( - void* context, - string_t item_path, - bool is_folder, - bool is_last); -typedef void (*BrowserWorkerLongLoadCallback)(void* context); - -void file_browser_worker_get_filename(string_t path, string_t name, bool trim_ext); - -BrowserWorker* file_browser_worker_alloc(string_t path, char* filter_ext, bool skip_assets); - -void file_browser_worker_free(BrowserWorker* browser); - -void file_browser_worker_set_callback_context(BrowserWorker* browser, void* context); - -void file_browser_worker_set_folder_callback( - BrowserWorker* browser, - BrowserWorkerFolderOpenCallback cb); - -void file_browser_worker_set_list_callback( - BrowserWorker* browser, - BrowserWorkerListLoadCallback cb); - -void file_browser_worker_set_item_callback( - BrowserWorker* browser, - BrowserWorkerListItemCallback cb); - -void file_browser_worker_set_long_load_callback( - BrowserWorker* browser, - BrowserWorkerLongLoadCallback cb); - -void file_browser_worker_folder_enter(BrowserWorker* browser, string_t path, int32_t item_idx); - -void file_browser_worker_folder_exit(BrowserWorker* browser); - -void file_browser_worker_load(BrowserWorker* browser, uint32_t offset, uint32_t count); - -#ifdef __cplusplus -} -#endif