Archive: Support viewing Disk Images with Virtual Mount

This commit is contained in:
Willy-JL
2024-02-20 06:14:38 +00:00
parent 39bd3f4e6d
commit e229367780
6 changed files with 73 additions and 8 deletions

View File

@@ -77,6 +77,13 @@ void archive_free(ArchiveApp* archive) {
archive->thread = NULL; archive->thread = NULL;
} }
if(archive->browser->disk_image) {
storage_virtual_quit(furi_record_open(RECORD_STORAGE));
furi_record_close(RECORD_STORAGE);
storage_file_free(archive->browser->disk_image);
archive->browser->disk_image = NULL;
}
// Loading // Loading
loading_free(archive->loading); loading_free(archive->loading);

View File

@@ -19,7 +19,8 @@ static void
browser->is_root = is_root; browser->is_root = is_root;
ArchiveTabEnum tab = archive_get_tab(browser); ArchiveTabEnum tab = archive_get_tab(browser);
if((item_cnt == 0) && (archive_is_home(browser)) && (tab != ArchiveTabBrowser)) { if((item_cnt == 0) && (archive_is_home(browser)) && (tab != ArchiveTabBrowser) &&
(tab != ArchiveTabDiskImage || !browser->disk_image)) {
archive_switch_tab(browser, browser->last_tab_switch_dir); archive_switch_tab(browser, browser->last_tab_switch_dir);
} else if(!furi_string_start_with_str(browser->path, "/app:")) { } else if(!furi_string_start_with_str(browser->path, "/app:")) {
with_view_model( with_view_model(
@@ -512,7 +513,8 @@ void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) {
static bool archive_is_dir_exists(FuriString* path) { static bool archive_is_dir_exists(FuriString* path) {
if(furi_string_equal(path, STORAGE_INT_PATH_PREFIX) || if(furi_string_equal(path, STORAGE_INT_PATH_PREFIX) ||
furi_string_equal(path, STORAGE_EXT_PATH_PREFIX)) { furi_string_equal(path, STORAGE_EXT_PATH_PREFIX) ||
furi_string_equal(path, STORAGE_MNT_PATH_PREFIX)) {
return true; return true;
} }
bool state = false; bool state = false;
@@ -592,7 +594,8 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) {
} }
} }
if(tab_empty && tab != ArchiveTabBrowser && tab != ArchiveTabInternal) { if(tab_empty && tab != ArchiveTabBrowser && tab != ArchiveTabInternal &&
(tab != ArchiveTabDiskImage || !browser->disk_image)) {
archive_switch_tab(browser, key); archive_switch_tab(browser, key);
} else { } else {
with_view_model( with_view_model(

View File

@@ -18,6 +18,7 @@ static const char* tab_default_paths[] = {
[ArchiveTabU2f] = "/app:u2f", [ArchiveTabU2f] = "/app:u2f",
[ArchiveTabApplications] = EXT_PATH("apps"), [ArchiveTabApplications] = EXT_PATH("apps"),
[ArchiveTabSearch] = "/app:search", [ArchiveTabSearch] = "/app:search",
[ArchiveTabDiskImage] = STORAGE_MNT_PATH_PREFIX,
[ArchiveTabInternal] = STORAGE_INT_PATH_PREFIX, [ArchiveTabInternal] = STORAGE_INT_PATH_PREFIX,
[ArchiveTabBrowser] = STORAGE_EXT_PATH_PREFIX, [ArchiveTabBrowser] = STORAGE_EXT_PATH_PREFIX,
}; };
@@ -54,6 +55,7 @@ static const ArchiveFileTypeEnum known_type[] = {
[ArchiveTabU2f] = ArchiveFileTypeU2f, [ArchiveTabU2f] = ArchiveFileTypeU2f,
[ArchiveTabApplications] = ArchiveFileTypeAppOrJs, [ArchiveTabApplications] = ArchiveFileTypeAppOrJs,
[ArchiveTabSearch] = ArchiveFileTypeSearch, [ArchiveTabSearch] = ArchiveFileTypeSearch,
[ArchiveTabDiskImage] = ArchiveFileTypeUnknown,
[ArchiveTabInternal] = ArchiveFileTypeUnknown, [ArchiveTabInternal] = ArchiveFileTypeUnknown,
[ArchiveTabBrowser] = ArchiveFileTypeUnknown, [ArchiveTabBrowser] = ArchiveFileTypeUnknown,
}; };

View File

@@ -81,6 +81,50 @@ static void archive_show_file(Loader* loader, const char* path) {
} }
} }
static void archive_mount_disk_image(ArchiveBrowserView* browser, ArchiveFile_t* selected) {
Storage* storage = furi_record_open(RECORD_STORAGE);
File* disk_image = NULL;
do {
if(browser->disk_image) {
// Deinit and recycle File object
if(storage_virtual_quit(storage) != FSE_OK) break;
storage_file_close(browser->disk_image);
disk_image = browser->disk_image;
browser->disk_image = NULL;
} else {
disk_image = storage_file_alloc(storage);
}
if(!storage_file_open(
disk_image,
furi_string_get_cstr(selected->path),
FSAM_READ | FSAM_WRITE,
FSOM_OPEN_EXISTING))
break;
FS_Error init = storage_virtual_init(storage, disk_image);
if(init == FSE_ALREADY_OPEN) {
if(storage_virtual_quit(storage) == FSE_OK) {
init = storage_virtual_init(storage, disk_image);
}
}
if(init != FSE_OK) break;
if(storage_virtual_mount(storage) != FSE_OK) {
storage_virtual_quit(storage);
break;
}
browser->disk_image = disk_image;
while(archive_get_tab(browser) != ArchiveTabDiskImage) {
archive_switch_tab(browser, TAB_LEFT);
}
} while(0);
if(disk_image && !browser->disk_image) storage_file_free(disk_image);
furi_record_close(RECORD_STORAGE);
}
static void static void
archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected, bool favorites) { archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected, bool favorites) {
Loader* loader = furi_record_open(RECORD_LOADER); Loader* loader = furi_record_open(RECORD_LOADER);
@@ -226,9 +270,14 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
consumed = true; consumed = true;
break; break;
case ArchiveBrowserEventFileMenuShow: case ArchiveBrowserEventFileMenuShow:
archive_show_file( if(selected->type == ArchiveFileTypeDiskImage &&
furi_record_open(RECORD_LOADER), furi_string_get_cstr(selected->path)); archive_get_tab(browser) != ArchiveTabDiskImage) {
furi_record_close(RECORD_LOADER); archive_mount_disk_image(browser, selected);
} else {
archive_show_file(
furi_record_open(RECORD_LOADER), furi_string_get_cstr(selected->path));
furi_record_close(RECORD_LOADER);
}
archive_show_file_menu(browser, false, false); archive_show_file_menu(browser, false, false);
consumed = true; consumed = true;
break; break;

View File

@@ -19,6 +19,7 @@ static const char* ArchiveTabNames[] = {
[ArchiveTabU2f] = "U2F", [ArchiveTabU2f] = "U2F",
[ArchiveTabApplications] = "Apps", [ArchiveTabApplications] = "Apps",
[ArchiveTabSearch] = "Search", [ArchiveTabSearch] = "Search",
[ArchiveTabDiskImage] = "Disk Image",
[ArchiveTabInternal] = "Internal", [ArchiveTabInternal] = "Internal",
[ArchiveTabBrowser] = "Browser", [ArchiveTabBrowser] = "Browser",
}; };
@@ -119,7 +120,7 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
if(selected->type != ArchiveFileTypeFolder) { if(selected->type != ArchiveFileTypeFolder) {
archive_menu_add_item( archive_menu_add_item(
menu_array_push_raw(model->context_menu), menu_array_push_raw(model->context_menu),
"Show", selected->type == ArchiveFileTypeDiskImage ? "Mount" : "Show",
ArchiveBrowserEventFileMenuShow); ArchiveBrowserEventFileMenuShow);
} }
} }
@@ -209,7 +210,8 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) {
model->files, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0)); model->files, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0));
file_type = file->type; file_type = file->type;
bool ext = model->tab_idx == ArchiveTabBrowser || bool ext = model->tab_idx == ArchiveTabBrowser ||
model->tab_idx == ArchiveTabInternal || model->tab_idx == ArchiveTabSearch; model->tab_idx == ArchiveTabInternal ||
model->tab_idx == ArchiveTabDiskImage || model->tab_idx == ArchiveTabSearch;
if(file_type == ArchiveFileTypeApplication) { if(file_type == ArchiveFileTypeApplication) {
if(file->custom_icon_data) { if(file->custom_icon_data) {
custom_icon_data = file->custom_icon_data; custom_icon_data = file->custom_icon_data;

View File

@@ -31,6 +31,7 @@ typedef enum {
ArchiveTabU2f, ArchiveTabU2f,
ArchiveTabApplications, ArchiveTabApplications,
ArchiveTabSearch, ArchiveTabSearch,
ArchiveTabDiskImage,
ArchiveTabInternal, ArchiveTabInternal,
ArchiveTabBrowser, ArchiveTabBrowser,
ArchiveTabTotal, ArchiveTabTotal,
@@ -90,6 +91,7 @@ struct ArchiveBrowserView {
InputKey last_tab_switch_dir; InputKey last_tab_switch_dir;
bool is_root; bool is_root;
FuriTimer* scroll_timer; FuriTimer* scroll_timer;
File* disk_image;
}; };
typedef struct { typedef struct {