mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-01 18:03:35 -07:00
0e3e1b352b
* feat(Desktop): Directories support for keybinds - Adds *RIGHT* button select in the file browser dialogs and changing the `Open File` action to `Open File/Directory` in `Settings > Desktop > Keybinds Setup`. This adds the ability to open to any directory in the Archive app, in addition to the default behavior of opening a file in it's default app. * line order mixup * Main Menu: Allow adding JS files (or any file) - Normal files and directories are now able to be added to then main menu and are run in their appropriate apps. - e.g. .txt files shown in text viewer, .js files are run in the JS Runner app, and folders are navigated to by the Archive app. All similar to the desktop keybinds functionality. - Icons are also assigned appropriately based on the extensions, though more could probably be added to the `loader_menu_get_ext_icon` function. - Also replaced some of the long arduous is_dir checks and just used the `storage_dir_exists` function since its already there and does the same. * should be checking `ext` for NULL * Move select_right at end of structs for binary compatibility apps may blindly reach into these structs so need to keep the basics in same structure for DialogsFileBrowserOptions this is even in public api and after compilation this would be incompatible with other firmwares even without reaching into private structs * Select menu item / folder for directories too * Move api below too * Keep ofw order here too * Refactor starting archive into desktop, less FuriString passing around * Dont leave main menu when launching archive * Simplify/fix a few things * Handle folders in run_with_default_app() * Update App -> Item naming in MNTM settings * Fix build * Explain pressing right * Update changelog --------- Co-authored-by: WillyJL <me@willyjl.dev>
165 lines
5.6 KiB
C
165 lines
5.6 KiB
C
#include "archive_i.h"
|
|
#include "helpers/archive_browser.h"
|
|
|
|
static bool archive_custom_event_callback(void* context, uint32_t event) {
|
|
furi_assert(context);
|
|
ArchiveApp* archive = context;
|
|
return scene_manager_handle_custom_event(archive->scene_manager, event);
|
|
}
|
|
|
|
static bool archive_back_event_callback(void* context) {
|
|
furi_assert(context);
|
|
ArchiveApp* archive = context;
|
|
return scene_manager_handle_back_event(archive->scene_manager);
|
|
}
|
|
|
|
static void archive_tick_event_callback(void* context) {
|
|
furi_assert(context);
|
|
ArchiveApp* archive = context;
|
|
scene_manager_handle_tick_event(archive->scene_manager);
|
|
}
|
|
|
|
static ArchiveApp* archive_alloc(void) {
|
|
ArchiveApp* archive = malloc(sizeof(ArchiveApp));
|
|
|
|
archive->gui = furi_record_open(RECORD_GUI);
|
|
archive->loader = furi_record_open(RECORD_LOADER);
|
|
archive->fav_move_str = furi_string_alloc();
|
|
archive->file_extension = furi_string_alloc();
|
|
|
|
archive->scene_manager = scene_manager_alloc(&archive_scene_handlers, archive);
|
|
archive->view_dispatcher = view_dispatcher_alloc();
|
|
|
|
ViewDispatcher* view_dispatcher = archive->view_dispatcher;
|
|
view_dispatcher_set_event_callback_context(view_dispatcher, archive);
|
|
view_dispatcher_set_custom_event_callback(view_dispatcher, archive_custom_event_callback);
|
|
view_dispatcher_set_navigation_event_callback(view_dispatcher, archive_back_event_callback);
|
|
view_dispatcher_set_tick_event_callback(view_dispatcher, archive_tick_event_callback, 100);
|
|
|
|
archive->dialogs = furi_record_open(RECORD_DIALOGS);
|
|
|
|
archive->text_input = text_input_alloc();
|
|
view_dispatcher_add_view(
|
|
view_dispatcher, ArchiveViewTextInput, text_input_get_view(archive->text_input));
|
|
|
|
archive->widget = widget_alloc();
|
|
view_dispatcher_add_view(
|
|
archive->view_dispatcher, ArchiveViewWidget, widget_get_view(archive->widget));
|
|
|
|
archive->view_stack = view_stack_alloc();
|
|
view_dispatcher_add_view(
|
|
view_dispatcher, ArchiveViewStack, view_stack_get_view(archive->view_stack));
|
|
|
|
archive->browser = browser_alloc();
|
|
with_view_model(
|
|
archive->browser->view,
|
|
ArchiveBrowserViewModel * model,
|
|
{ model->archive = archive; },
|
|
true);
|
|
view_dispatcher_add_view(
|
|
archive->view_dispatcher, ArchiveViewBrowser, archive_browser_get_view(archive->browser));
|
|
|
|
// Loading
|
|
archive->loading = loading_alloc();
|
|
|
|
return archive;
|
|
}
|
|
|
|
void archive_free(ArchiveApp* archive) {
|
|
furi_assert(archive);
|
|
ViewDispatcher* view_dispatcher = archive->view_dispatcher;
|
|
|
|
scene_manager_set_scene_state(archive->scene_manager, ArchiveAppSceneInfo, false);
|
|
scene_manager_set_scene_state(archive->scene_manager, ArchiveAppSceneSearch, false);
|
|
if(archive->info_thread) {
|
|
furi_thread_join(archive->info_thread);
|
|
furi_thread_free(archive->info_thread);
|
|
archive->info_thread = NULL;
|
|
}
|
|
if(archive->search_thread) {
|
|
furi_thread_join(archive->search_thread);
|
|
furi_thread_free(archive->search_thread);
|
|
archive->search_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);
|
|
|
|
view_dispatcher_remove_view(view_dispatcher, ArchiveViewTextInput);
|
|
text_input_free(archive->text_input);
|
|
|
|
view_dispatcher_remove_view(view_dispatcher, ArchiveViewWidget);
|
|
widget_free(archive->widget);
|
|
|
|
view_dispatcher_remove_view(view_dispatcher, ArchiveViewStack);
|
|
view_stack_free(archive->view_stack);
|
|
|
|
view_dispatcher_remove_view(view_dispatcher, ArchiveViewBrowser);
|
|
|
|
view_dispatcher_free(archive->view_dispatcher);
|
|
scene_manager_free(archive->scene_manager);
|
|
|
|
browser_free(archive->browser);
|
|
furi_string_free(archive->fav_move_str);
|
|
furi_string_free(archive->file_extension);
|
|
|
|
furi_record_close(RECORD_DIALOGS);
|
|
archive->dialogs = NULL;
|
|
|
|
furi_record_close(RECORD_LOADER);
|
|
archive->loader = NULL;
|
|
furi_record_close(RECORD_GUI);
|
|
archive->gui = NULL;
|
|
|
|
free(archive);
|
|
}
|
|
|
|
void archive_show_loading_popup(ArchiveApp* context, bool show) {
|
|
ViewStack* view_stack = context->view_stack;
|
|
Loading* loading = context->loading;
|
|
|
|
if(show) {
|
|
// Raise timer priority so that animations can play
|
|
furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
|
|
view_stack_add_view(view_stack, loading_get_view(loading));
|
|
} else {
|
|
view_stack_remove_view(view_stack, loading_get_view(loading));
|
|
// Restore default timer priority
|
|
furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal);
|
|
}
|
|
}
|
|
|
|
int32_t archive_app(void* p) {
|
|
FuriString* path = (FuriString*)p;
|
|
|
|
ArchiveApp* archive = archive_alloc();
|
|
view_dispatcher_attach_to_gui(
|
|
archive->view_dispatcher, archive->gui, ViewDispatcherTypeFullscreen);
|
|
|
|
// If we are sent a path from context, set it in the browser
|
|
if(path && !furi_string_empty(path)) {
|
|
archive_set_tab(archive->browser, ArchiveTabBrowser);
|
|
furi_string_set(archive->browser->path, path);
|
|
archive->browser->is_root = false;
|
|
archive_file_browser_set_path(
|
|
archive->browser,
|
|
archive->browser->path,
|
|
archive_get_tab_ext(ArchiveTabBrowser),
|
|
false,
|
|
!momentum_settings.show_hidden_files);
|
|
}
|
|
|
|
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneBrowser);
|
|
view_dispatcher_run(archive->view_dispatcher);
|
|
|
|
archive_free(archive);
|
|
return 0;
|
|
}
|