From f5ac0166a68117f89033bfd2fe351ce99a4565c6 Mon Sep 17 00:00:00 2001 From: Alexander Bays Date: Sun, 15 Dec 2024 14:56:37 -0600 Subject: [PATCH] feat(Archive): Adds dynamic paths to browser tab I thought it would be cool to be able to see when I was in say the `apps_data/flipchess` folder, or some other nested folder, and have "flipchess" be shown rather than the just "Browser" all the time. It's not a huge or really crucial change, just a personal modification that some people may also find useful. --- .../main/archive/helpers/archive_browser.c | 3 + .../main/archive/views/archive_browser_view.c | 70 ++++++++++++++++++- .../main/archive/views/archive_browser_view.h | 4 ++ ...momentum_app_scene_interface_filebrowser.c | 26 +++++++ lib/momentum/settings.c | 2 + lib/momentum/settings.h | 9 +++ 6 files changed, 113 insertions(+), 1 deletion(-) diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index ea93c9e055..695f11c78f 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -34,6 +34,7 @@ static void model->list_offset = 0; model->list_loading = true; model->folder_loading = false; + browser->path_changed = true; }, false); archive_update_offset(browser); @@ -556,6 +557,7 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { archive_set_tab(browser, tab); furi_string_set(browser->path, archive_get_default_path(tab)); + browser->path_changed = true; bool tab_empty = true; bool is_app_tab = furi_string_start_with_str(browser->path, "/app:"); if(tab == ArchiveTabFavorites) { @@ -644,6 +646,7 @@ void archive_leave_dir(ArchiveBrowserView* browser) { size_t dirname_start = furi_string_search_rchar(browser->path, '/'); furi_string_left(browser->path, dirname_start); + browser->path_changed = true; const char* switch_ext = NULL; switch(archive_get_tab(browser)) { diff --git a/applications/main/archive/views/archive_browser_view.c b/applications/main/archive/views/archive_browser_view.c index ecdf483415..e82d52dcf4 100644 --- a/applications/main/archive/views/archive_browser_view.c +++ b/applications/main/archive/views/archive_browser_view.c @@ -58,6 +58,53 @@ void archive_browser_set_callback( browser->context = context; } +static void archive_update_formatted_path(ArchiveBrowserViewModel* model) { + ArchiveBrowserView* browser = model->archive->browser; + if(!browser->path_changed) { + return; + } + + ArchiveTabEnum tab = archive_get_tab(browser); + if(momentum_settings.show_browser_path && !archive_is_home(browser)) { + if(momentum_settings.show_browser_path == BrowserPathFull) { + furi_string_set(browser->formatted_path, browser->path); + } else if(momentum_settings.show_browser_path == BrowserPathBrief) { + furi_string_reset(browser->formatted_path); + + char path_buf[256]; + strncpy(path_buf, furi_string_get_cstr(browser->path), sizeof(path_buf) - 1); + path_buf[sizeof(path_buf) - 1] = '\0'; + char* token = strtok(path_buf, "/"); + + while(token != NULL) { + char* next = strtok(NULL, "/"); + if(next != NULL) { + furi_string_cat_printf(browser->formatted_path, "/%c", token[0]); + } else { + furi_string_cat_printf(browser->formatted_path, "/%s", token); + } + token = next; + } + } else { + size_t r_slash = furi_string_search_rchar(browser->path, '/'); + if(r_slash != FURI_STRING_FAILURE) { + furi_string_set_n( + browser->formatted_path, + browser->path, + r_slash + 1, + furi_string_size(browser->path) - r_slash - 1); + } else { + furi_string_set(browser->formatted_path, browser->path); + } + } + } else { + furi_string_set(browser->formatted_path, ArchiveTabNames[tab]); + } + + furi_string_set(browser->prev_path, browser->path); + browser->path_changed = false; +} + static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) { if(menu_array_size(model->context_menu) == 0) { // Need init context menu @@ -279,6 +326,9 @@ static void archive_render_status_bar(Canvas* canvas, ArchiveBrowserViewModel* m if(model->tab_idx == ArchiveTabSearch && scene_manager_get_scene_state(model->archive->scene_manager, ArchiveAppSceneSearch)) { tab_name = "Searching"; + } else { + archive_update_formatted_path(model); + tab_name = furi_string_get_cstr(model->archive->browser->formatted_path); } bool clip = model->clipboard != NULL; @@ -293,7 +343,20 @@ static void archive_render_status_bar(Canvas* canvas, ArchiveBrowserViewModel* m canvas_draw_rframe(canvas, 0, 0, 51, 13, 1); // frame canvas_draw_line(canvas, 49, 1, 49, 11); // shadow right canvas_draw_line(canvas, 1, 11, 49, 11); // shadow bottom - canvas_draw_str_aligned(canvas, 25, 9, AlignCenter, AlignBottom, tab_name); + + size_t text_width = canvas_string_width(canvas, tab_name); + if(text_width > 45) { + elements_scrollable_text_line( + canvas, + 3, + 9, + 45, + model->archive->browser->formatted_path, + model->scroll_counter, + false); + } else { + canvas_draw_str_aligned(canvas, 25, 9, AlignCenter, AlignBottom, tab_name); + } if(clip) { canvas_draw_rframe(canvas, 69, 0, 25, 13, 1); @@ -593,6 +656,9 @@ ArchiveBrowserView* browser_alloc(void) { browser->scroll_timer = furi_timer_alloc(browser_scroll_timer, FuriTimerTypePeriodic, browser); browser->path = furi_string_alloc_set(archive_get_default_path(TAB_DEFAULT)); + browser->prev_path = furi_string_alloc(); + browser->formatted_path = furi_string_alloc(); + browser->path_changed = true; with_view_model( browser->view, @@ -626,6 +692,8 @@ void browser_free(ArchiveBrowserView* browser) { false); furi_string_free(browser->path); + furi_string_free(browser->prev_path); + furi_string_free(browser->formatted_path); view_free(browser->view); free(browser); diff --git a/applications/main/archive/views/archive_browser_view.h b/applications/main/archive/views/archive_browser_view.h index 6a35cb145b..b3b233052b 100644 --- a/applications/main/archive/views/archive_browser_view.h +++ b/applications/main/archive/views/archive_browser_view.h @@ -3,6 +3,7 @@ #include "../helpers/archive_files.h" #include "../helpers/archive_favorites.h" +#include "archive/archive.h" #include #include #include @@ -88,6 +89,9 @@ struct ArchiveBrowserView { ArchiveBrowserViewCallback callback; void* context; FuriString* path; + FuriString* prev_path; + FuriString* formatted_path; + bool path_changed; InputKey last_tab_switch_dir; bool is_root; FuriTimer* scroll_timer; diff --git a/applications/main/momentum_app/scenes/momentum_app_scene_interface_filebrowser.c b/applications/main/momentum_app/scenes/momentum_app_scene_interface_filebrowser.c index 0a3f98b12e..c10807460f 100644 --- a/applications/main/momentum_app/scenes/momentum_app_scene_interface_filebrowser.c +++ b/applications/main/momentum_app/scenes/momentum_app_scene_interface_filebrowser.c @@ -7,6 +7,13 @@ enum VarItemListIndex { VarItemListIndexFavoriteTimeout, }; +const char* const browser_path_names[BrowserPathModeCount] = { + "OFF", + "Current", + "Brief", + "Full", +}; + void momentum_app_scene_interface_filebrowser_var_item_list_callback(void* context, uint32_t index) { MomentumApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, index); @@ -38,6 +45,15 @@ static void app->save_settings = true; } +static void + momentum_app_scene_interface_filebrowser_show_browser_path_changed(VariableItem* item) { + MomentumApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + variable_item_set_current_value_text(item, browser_path_names[index]); + momentum_settings.show_browser_path = index; + app->save_settings = true; +} + static void momentum_app_scene_interface_filebrowser_favorite_timeout_changed(VariableItem* item) { MomentumApp* app = variable_item_get_context(item); uint32_t value = variable_item_get_current_value_index(item); @@ -80,6 +96,16 @@ void momentum_app_scene_interface_filebrowser_on_enter(void* context) { variable_item_set_current_value_index(item, momentum_settings.show_internal_tab); variable_item_set_current_value_text(item, momentum_settings.show_internal_tab ? "ON" : "OFF"); + item = variable_item_list_add( + var_item_list, + "Show Browser Path", + BrowserPathModeCount, + momentum_app_scene_interface_filebrowser_show_browser_path_changed, + app); + variable_item_set_current_value_index(item, momentum_settings.show_browser_path); + variable_item_set_current_value_text( + item, browser_path_names[momentum_settings.show_browser_path]); + item = variable_item_list_add( var_item_list, "Favorite Timeout", diff --git a/lib/momentum/settings.c b/lib/momentum/settings.c index 315124c7c4..b24596e445 100644 --- a/lib/momentum/settings.c +++ b/lib/momentum/settings.c @@ -29,6 +29,7 @@ MomentumSettings momentum_settings = { .sort_dirs_first = true, // ON .show_hidden_files = false, // OFF .show_internal_tab = false, // OFF + .show_browser_path = BrowserPathOff, // OFF .favorite_timeout = 0, // OFF .dark_mode = false, // OFF .rgb_backlight = false, // OFF @@ -98,6 +99,7 @@ static const struct { {setting_bool(sort_dirs_first)}, {setting_bool(show_hidden_files)}, {setting_bool(show_internal_tab)}, + {setting_bool(show_browser_path)}, {setting_uint(favorite_timeout, 0, 60)}, {setting_bool(dark_mode)}, {setting_bool(rgb_backlight)}, diff --git a/lib/momentum/settings.h b/lib/momentum/settings.h index ee13411313..f55034271e 100644 --- a/lib/momentum/settings.h +++ b/lib/momentum/settings.h @@ -54,6 +54,14 @@ typedef union __attribute__((packed)) { uint32_t value; } ScreenFrameColor; +typedef enum { + BrowserPathOff, + BrowserPathCurrent, + BrowserPathBrief, + BrowserPathFull, + BrowserPathModeCount, +} BrowserPathMode; + typedef struct { char asset_pack[ASSET_PACKS_NAME_LEN]; uint32_t anim_speed; @@ -77,6 +85,7 @@ typedef struct { bool sort_dirs_first; bool show_hidden_files; bool show_internal_tab; + BrowserPathMode show_browser_path; uint32_t favorite_timeout; bool dark_mode; bool rgb_backlight;