mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2025-10-09 22:52:32 +02:00
Archive: Add dynamic paths to browser tab (#322)
* 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. * fix(Archive): Clean up, built-ins, safer Cleaned up `archive_update_formatted_path` function using switch case, and also using the built in furi functions where possible. Also removed the arbitrary and unnecessary `path_buf[256]`, making formatting the path in the Brief section more memory safe. * Rename setting and use setting_enum() * Remove prev_path * Enum names * Single text draw call * Rename to statusbar title * Revert "Rename to statusbar title" This reverts commit243f2a754f
. * Revert "Single text draw call" This reverts commit3bbe30449b
. * Simpler fix * Shorter setting label * Update changelog --------- Co-authored-by: Willy-JL <49810075+Willy-JL@users.noreply.github.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
- Apps:
|
- Apps:
|
||||||
- Games: Pinball0 (by @rdefeo)
|
- Games: Pinball0 (by @rdefeo)
|
||||||
- NFC: Metroflip (by @luu176)
|
- 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)
|
- CLI: Add `clear` and `cls` commands, add `did you mean ...?` command suggestion (#342 by @dexvleads)
|
||||||
- Main Menu: Add coverflow menu style (#314 by @CodyTolene)
|
- Main Menu: Add coverflow menu style (#314 by @CodyTolene)
|
||||||
- BadKB: Added german Mac keyboard Layout (#325 by @Cloudy261)
|
- BadKB: Added german Mac keyboard Layout (#325 by @Cloudy261)
|
||||||
|
@@ -34,6 +34,7 @@ static void
|
|||||||
model->list_offset = 0;
|
model->list_offset = 0;
|
||||||
model->list_loading = true;
|
model->list_loading = true;
|
||||||
model->folder_loading = false;
|
model->folder_loading = false;
|
||||||
|
browser->path_changed = true;
|
||||||
},
|
},
|
||||||
false);
|
false);
|
||||||
archive_update_offset(browser);
|
archive_update_offset(browser);
|
||||||
@@ -556,6 +557,7 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
|
|||||||
archive_set_tab(browser, tab);
|
archive_set_tab(browser, tab);
|
||||||
|
|
||||||
furi_string_set(browser->path, archive_get_default_path(tab));
|
furi_string_set(browser->path, archive_get_default_path(tab));
|
||||||
|
browser->path_changed = true;
|
||||||
bool tab_empty = true;
|
bool tab_empty = true;
|
||||||
bool is_app_tab = furi_string_start_with_str(browser->path, "/app:");
|
bool is_app_tab = furi_string_start_with_str(browser->path, "/app:");
|
||||||
if(tab == ArchiveTabFavorites) {
|
if(tab == ArchiveTabFavorites) {
|
||||||
@@ -644,6 +646,7 @@ void archive_leave_dir(ArchiveBrowserView* browser) {
|
|||||||
|
|
||||||
size_t dirname_start = furi_string_search_rchar(browser->path, '/');
|
size_t dirname_start = furi_string_search_rchar(browser->path, '/');
|
||||||
furi_string_left(browser->path, dirname_start);
|
furi_string_left(browser->path, dirname_start);
|
||||||
|
browser->path_changed = true;
|
||||||
|
|
||||||
const char* switch_ext = NULL;
|
const char* switch_ext = NULL;
|
||||||
switch(archive_get_tab(browser)) {
|
switch(archive_get_tab(browser)) {
|
||||||
|
@@ -58,6 +58,58 @@ void archive_browser_set_callback(
|
|||||||
browser->context = context;
|
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) {
|
static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||||
if(menu_array_size(model->context_menu) == 0) {
|
if(menu_array_size(model->context_menu) == 0) {
|
||||||
// Need init context menu
|
// 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) {
|
static void archive_render_status_bar(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||||
furi_assert(model);
|
furi_assert(model);
|
||||||
|
|
||||||
const char* tab_name = ArchiveTabNames[model->tab_idx];
|
const char* tab_name = NULL;
|
||||||
if(model->tab_idx == ArchiveTabSearch &&
|
if(model->tab_idx == ArchiveTabSearch) {
|
||||||
scene_manager_get_scene_state(model->archive->scene_manager, ArchiveAppSceneSearch)) {
|
if(scene_manager_get_scene_state(model->archive->scene_manager, ArchiveAppSceneSearch)) {
|
||||||
tab_name = "Searching";
|
tab_name = "Searching";
|
||||||
|
} else {
|
||||||
|
tab_name = ArchiveTabNames[model->tab_idx];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
archive_update_formatted_path(model);
|
||||||
}
|
}
|
||||||
bool clip = model->clipboard != NULL;
|
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_rframe(canvas, 0, 0, 51, 13, 1); // frame
|
||||||
canvas_draw_line(canvas, 49, 1, 49, 11); // shadow right
|
canvas_draw_line(canvas, 49, 1, 49, 11); // shadow right
|
||||||
canvas_draw_line(canvas, 1, 11, 49, 11); // shadow bottom
|
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) {
|
if(clip) {
|
||||||
canvas_draw_rframe(canvas, 69, 0, 25, 13, 1);
|
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->scroll_timer = furi_timer_alloc(browser_scroll_timer, FuriTimerTypePeriodic, browser);
|
||||||
|
|
||||||
browser->path = furi_string_alloc_set(archive_get_default_path(TAB_DEFAULT));
|
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(
|
with_view_model(
|
||||||
browser->view,
|
browser->view,
|
||||||
@@ -626,6 +697,7 @@ void browser_free(ArchiveBrowserView* browser) {
|
|||||||
false);
|
false);
|
||||||
|
|
||||||
furi_string_free(browser->path);
|
furi_string_free(browser->path);
|
||||||
|
furi_string_free(browser->formatted_path);
|
||||||
|
|
||||||
view_free(browser->view);
|
view_free(browser->view);
|
||||||
free(browser);
|
free(browser);
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include "../helpers/archive_files.h"
|
#include "../helpers/archive_files.h"
|
||||||
#include "../helpers/archive_favorites.h"
|
#include "../helpers/archive_favorites.h"
|
||||||
|
|
||||||
|
#include "archive/archive.h"
|
||||||
#include <gui/gui_i.h>
|
#include <gui/gui_i.h>
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
#include <gui/canvas.h>
|
#include <gui/canvas.h>
|
||||||
@@ -88,6 +89,8 @@ struct ArchiveBrowserView {
|
|||||||
ArchiveBrowserViewCallback callback;
|
ArchiveBrowserViewCallback callback;
|
||||||
void* context;
|
void* context;
|
||||||
FuriString* path;
|
FuriString* path;
|
||||||
|
FuriString* formatted_path;
|
||||||
|
bool path_changed;
|
||||||
InputKey last_tab_switch_dir;
|
InputKey last_tab_switch_dir;
|
||||||
bool is_root;
|
bool is_root;
|
||||||
FuriTimer* scroll_timer;
|
FuriTimer* scroll_timer;
|
||||||
|
@@ -7,6 +7,13 @@ enum VarItemListIndex {
|
|||||||
VarItemListIndexFavoriteTimeout,
|
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) {
|
void momentum_app_scene_interface_filebrowser_var_item_list_callback(void* context, uint32_t index) {
|
||||||
MomentumApp* app = context;
|
MomentumApp* app = context;
|
||||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||||
@@ -38,6 +45,15 @@ static void
|
|||||||
app->save_settings = true;
|
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) {
|
static void momentum_app_scene_interface_filebrowser_favorite_timeout_changed(VariableItem* item) {
|
||||||
MomentumApp* app = variable_item_get_context(item);
|
MomentumApp* app = variable_item_get_context(item);
|
||||||
uint32_t value = variable_item_get_current_value_index(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_index(item, momentum_settings.show_internal_tab);
|
||||||
variable_item_set_current_value_text(item, momentum_settings.show_internal_tab ? "ON" : "OFF");
|
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(
|
item = variable_item_list_add(
|
||||||
var_item_list,
|
var_item_list,
|
||||||
"Favorite Timeout",
|
"Favorite Timeout",
|
||||||
|
@@ -30,6 +30,7 @@ MomentumSettings momentum_settings = {
|
|||||||
.sort_dirs_first = true, // ON
|
.sort_dirs_first = true, // ON
|
||||||
.show_hidden_files = false, // OFF
|
.show_hidden_files = false, // OFF
|
||||||
.show_internal_tab = false, // OFF
|
.show_internal_tab = false, // OFF
|
||||||
|
.browser_path_mode = BrowserPathOff, // OFF
|
||||||
.favorite_timeout = 0, // OFF
|
.favorite_timeout = 0, // OFF
|
||||||
.dark_mode = false, // OFF
|
.dark_mode = false, // OFF
|
||||||
.rgb_backlight = false, // OFF
|
.rgb_backlight = false, // OFF
|
||||||
@@ -100,6 +101,7 @@ static const struct {
|
|||||||
{setting_bool(sort_dirs_first)},
|
{setting_bool(sort_dirs_first)},
|
||||||
{setting_bool(show_hidden_files)},
|
{setting_bool(show_hidden_files)},
|
||||||
{setting_bool(show_internal_tab)},
|
{setting_bool(show_internal_tab)},
|
||||||
|
{setting_enum(browser_path_mode, BrowserPathModeCount)},
|
||||||
{setting_uint(favorite_timeout, 0, 60)},
|
{setting_uint(favorite_timeout, 0, 60)},
|
||||||
{setting_bool(dark_mode)},
|
{setting_bool(dark_mode)},
|
||||||
{setting_bool(rgb_backlight)},
|
{setting_bool(rgb_backlight)},
|
||||||
|
@@ -55,6 +55,14 @@ typedef union __attribute__((packed)) {
|
|||||||
uint32_t value;
|
uint32_t value;
|
||||||
} ScreenFrameColor;
|
} ScreenFrameColor;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BrowserPathOff,
|
||||||
|
BrowserPathCurrent,
|
||||||
|
BrowserPathBrief,
|
||||||
|
BrowserPathFull,
|
||||||
|
BrowserPathModeCount,
|
||||||
|
} BrowserPathMode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char asset_pack[ASSET_PACKS_NAME_LEN];
|
char asset_pack[ASSET_PACKS_NAME_LEN];
|
||||||
uint32_t anim_speed;
|
uint32_t anim_speed;
|
||||||
@@ -79,6 +87,7 @@ typedef struct {
|
|||||||
bool sort_dirs_first;
|
bool sort_dirs_first;
|
||||||
bool show_hidden_files;
|
bool show_hidden_files;
|
||||||
bool show_internal_tab;
|
bool show_internal_tab;
|
||||||
|
BrowserPathMode browser_path_mode;
|
||||||
uint32_t favorite_timeout;
|
uint32_t favorite_timeout;
|
||||||
bool dark_mode;
|
bool dark_mode;
|
||||||
bool rgb_backlight;
|
bool rgb_backlight;
|
||||||
|
Reference in New Issue
Block a user