diff --git a/CHANGELOG.md b/CHANGELOG.md index d01ea93de..7abbc22ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Apps: - Games: Pinball0 (by @rdefeo) - NFC: Metroflip (by @luu176) +- Archive: Setting to show dynamic path in file browser statusbar (#322 by @956MB) - CLI: Add `clear` and `cls` commands, add `did you mean ...?` command suggestion (#342 by @dexvleads) - Main Menu: Add coverflow menu style (#314 by @CodyTolene) - BadKB: Added german Mac keyboard Layout (#325 by @Cloudy261) diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index ea93c9e05..695f11c78 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 ecdf48341..658ae1a92 100644 --- a/applications/main/archive/views/archive_browser_view.c +++ b/applications/main/archive/views/archive_browser_view.c @@ -58,6 +58,58 @@ 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; + } + + if(momentum_settings.browser_path_mode == BrowserPathOff || archive_is_home(browser)) { + furi_string_set(browser->formatted_path, ArchiveTabNames[model->tab_idx]); + } else { + const char* path = furi_string_get_cstr(browser->path); + switch(momentum_settings.browser_path_mode) { + case BrowserPathFull: + furi_string_set(browser->formatted_path, browser->path); + break; + + case BrowserPathBrief: { + furi_string_reset(browser->formatted_path); + FuriString* token = furi_string_alloc(); + FuriString* remaining = furi_string_alloc_set(path); + + while(furi_string_size(remaining) > 0) { + size_t slash_pos = furi_string_search_char(remaining, '/'); + if(slash_pos == FURI_STRING_FAILURE) { + furi_string_cat_printf( + browser->formatted_path, "/%s", furi_string_get_cstr(remaining)); + break; + } + furi_string_set_n(token, remaining, 0, slash_pos); + if(furi_string_size(token) > 0) { + furi_string_cat_printf( + browser->formatted_path, "/%c", furi_string_get_char(token, 0)); + } + furi_string_right(remaining, slash_pos + 1); + } + + furi_string_free(token); + furi_string_free(remaining); + break; + } + + case BrowserPathCurrent: + path_extract_basename(path, browser->formatted_path); + break; + + default: + break; + } + } + + 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 @@ -275,10 +327,15 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) { static void archive_render_status_bar(Canvas* canvas, ArchiveBrowserViewModel* model) { furi_assert(model); - const char* tab_name = ArchiveTabNames[model->tab_idx]; - if(model->tab_idx == ArchiveTabSearch && - scene_manager_get_scene_state(model->archive->scene_manager, ArchiveAppSceneSearch)) { - tab_name = "Searching"; + const char* tab_name = NULL; + if(model->tab_idx == ArchiveTabSearch) { + if(scene_manager_get_scene_state(model->archive->scene_manager, ArchiveAppSceneSearch)) { + tab_name = "Searching"; + } else { + tab_name = ArchiveTabNames[model->tab_idx]; + } + } else { + archive_update_formatted_path(model); } bool clip = model->clipboard != NULL; @@ -293,7 +350,19 @@ 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); + if(tab_name) { + canvas_draw_str_aligned(canvas, 25, 9, AlignCenter, AlignBottom, tab_name); + } else { + elements_scrollable_text_line_centered( + canvas, + 25, + 9, + 45, + model->archive->browser->formatted_path, + model->scroll_counter, + false, + true); + } if(clip) { canvas_draw_rframe(canvas, 69, 0, 25, 13, 1); @@ -593,6 +662,8 @@ 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->formatted_path = furi_string_alloc(); + browser->path_changed = true; with_view_model( browser->view, @@ -626,6 +697,7 @@ void browser_free(ArchiveBrowserView* browser) { false); furi_string_free(browser->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 6a35cb145..b5db1b96d 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,8 @@ struct ArchiveBrowserView { ArchiveBrowserViewCallback callback; void* context; FuriString* 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 0a3f98b12..7032b2f9c 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_browser_path_mode_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.browser_path_mode = 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 Path", + BrowserPathModeCount, + momentum_app_scene_interface_filebrowser_browser_path_mode_changed, + app); + variable_item_set_current_value_index(item, momentum_settings.browser_path_mode); + variable_item_set_current_value_text( + item, browser_path_names[momentum_settings.browser_path_mode]); + item = variable_item_list_add( var_item_list, "Favorite Timeout", diff --git a/lib/momentum/settings.c b/lib/momentum/settings.c index 30fc3480b..9da9a4762 100644 --- a/lib/momentum/settings.c +++ b/lib/momentum/settings.c @@ -30,6 +30,7 @@ MomentumSettings momentum_settings = { .sort_dirs_first = true, // ON .show_hidden_files = false, // OFF .show_internal_tab = false, // OFF + .browser_path_mode = BrowserPathOff, // OFF .favorite_timeout = 0, // OFF .dark_mode = false, // OFF .rgb_backlight = false, // OFF @@ -100,6 +101,7 @@ static const struct { {setting_bool(sort_dirs_first)}, {setting_bool(show_hidden_files)}, {setting_bool(show_internal_tab)}, + {setting_enum(browser_path_mode, BrowserPathModeCount)}, {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 54cc74e53..573924ee6 100644 --- a/lib/momentum/settings.h +++ b/lib/momentum/settings.h @@ -55,6 +55,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; @@ -79,6 +87,7 @@ typedef struct { bool sort_dirs_first; bool show_hidden_files; bool show_internal_tab; + BrowserPathMode browser_path_mode; uint32_t favorite_timeout; bool dark_mode; bool rgb_backlight;