mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-11 06:09:08 -07:00
Archive: Support viewing Disk Images with Virtual Mount
This commit is contained in:
@@ -77,6 +77,13 @@ void archive_free(ArchiveApp* archive) {
|
||||
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_free(archive->loading);
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@ static void
|
||||
browser->is_root = is_root;
|
||||
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);
|
||||
} else if(!furi_string_start_with_str(browser->path, "/app:")) {
|
||||
with_view_model(
|
||||
@@ -512,7 +513,8 @@ void archive_favorites_move_mode(ArchiveBrowserView* browser, bool active) {
|
||||
|
||||
static bool archive_is_dir_exists(FuriString* path) {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
} else {
|
||||
with_view_model(
|
||||
|
||||
@@ -18,6 +18,7 @@ static const char* tab_default_paths[] = {
|
||||
[ArchiveTabU2f] = "/app:u2f",
|
||||
[ArchiveTabApplications] = EXT_PATH("apps"),
|
||||
[ArchiveTabSearch] = "/app:search",
|
||||
[ArchiveTabDiskImage] = STORAGE_MNT_PATH_PREFIX,
|
||||
[ArchiveTabInternal] = STORAGE_INT_PATH_PREFIX,
|
||||
[ArchiveTabBrowser] = STORAGE_EXT_PATH_PREFIX,
|
||||
};
|
||||
@@ -54,6 +55,7 @@ static const ArchiveFileTypeEnum known_type[] = {
|
||||
[ArchiveTabU2f] = ArchiveFileTypeU2f,
|
||||
[ArchiveTabApplications] = ArchiveFileTypeAppOrJs,
|
||||
[ArchiveTabSearch] = ArchiveFileTypeSearch,
|
||||
[ArchiveTabDiskImage] = ArchiveFileTypeUnknown,
|
||||
[ArchiveTabInternal] = ArchiveFileTypeUnknown,
|
||||
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected, bool favorites) {
|
||||
Loader* loader = furi_record_open(RECORD_LOADER);
|
||||
@@ -226,9 +270,14 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
break;
|
||||
case ArchiveBrowserEventFileMenuShow:
|
||||
archive_show_file(
|
||||
furi_record_open(RECORD_LOADER), furi_string_get_cstr(selected->path));
|
||||
furi_record_close(RECORD_LOADER);
|
||||
if(selected->type == ArchiveFileTypeDiskImage &&
|
||||
archive_get_tab(browser) != ArchiveTabDiskImage) {
|
||||
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);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
@@ -19,6 +19,7 @@ static const char* ArchiveTabNames[] = {
|
||||
[ArchiveTabU2f] = "U2F",
|
||||
[ArchiveTabApplications] = "Apps",
|
||||
[ArchiveTabSearch] = "Search",
|
||||
[ArchiveTabDiskImage] = "Disk Image",
|
||||
[ArchiveTabInternal] = "Internal",
|
||||
[ArchiveTabBrowser] = "Browser",
|
||||
};
|
||||
@@ -119,7 +120,7 @@ static void render_item_menu(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
if(selected->type != ArchiveFileTypeFolder) {
|
||||
archive_menu_add_item(
|
||||
menu_array_push_raw(model->context_menu),
|
||||
"Show",
|
||||
selected->type == ArchiveFileTypeDiskImage ? "Mount" : "Show",
|
||||
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));
|
||||
file_type = file->type;
|
||||
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->custom_icon_data) {
|
||||
custom_icon_data = file->custom_icon_data;
|
||||
|
||||
@@ -31,6 +31,7 @@ typedef enum {
|
||||
ArchiveTabU2f,
|
||||
ArchiveTabApplications,
|
||||
ArchiveTabSearch,
|
||||
ArchiveTabDiskImage,
|
||||
ArchiveTabInternal,
|
||||
ArchiveTabBrowser,
|
||||
ArchiveTabTotal,
|
||||
@@ -90,6 +91,7 @@ struct ArchiveBrowserView {
|
||||
InputKey last_tab_switch_dir;
|
||||
bool is_root;
|
||||
FuriTimer* scroll_timer;
|
||||
File* disk_image;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
||||
Reference in New Issue
Block a user