[FL-2633] Move files from /int to /ext on SD mount #1384
Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									fd498bdfcf
								
							
						
					
					
						commit
						2caa5c3064
					
				| @ -190,6 +190,14 @@ FS_Error storage_common_rename(Storage* storage, const char* old_path, const cha | ||||
|  */ | ||||
| FS_Error storage_common_copy(Storage* storage, const char* old_path, const char* new_path); | ||||
| 
 | ||||
| /** Copy one folder contents into another with rename of all conflicting files
 | ||||
|  * @param app pointer to the api | ||||
|  * @param old_path old path | ||||
|  * @param new_path new path | ||||
|  * @return FS_Error operation result | ||||
|  */ | ||||
| FS_Error storage_common_merge(Storage* storage, const char* old_path, const char* new_path); | ||||
| 
 | ||||
| /** Creates a directory
 | ||||
|  * @param app pointer to the api | ||||
|  * @param path directory path | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| #include "furi/log.h" | ||||
| #include <furi/record.h> | ||||
| #include <m-string.h> | ||||
| #include "storage.h" | ||||
| @ -5,8 +6,10 @@ | ||||
| #include "storage_message.h" | ||||
| #include <toolbox/stream/file_stream.h> | ||||
| #include <toolbox/dir_walk.h> | ||||
| #include "toolbox/path.h" | ||||
| 
 | ||||
| #define MAX_NAME_LENGTH 256 | ||||
| #define MAX_EXT_LEN 16 | ||||
| 
 | ||||
| #define TAG "StorageAPI" | ||||
| 
 | ||||
| @ -436,6 +439,131 @@ FS_Error storage_common_copy(Storage* storage, const char* old_path, const char* | ||||
|     return error; | ||||
| } | ||||
| 
 | ||||
| static FS_Error | ||||
|     storage_merge_recursive(Storage* storage, const char* old_path, const char* new_path) { | ||||
|     FS_Error error = storage_common_mkdir(storage, new_path); | ||||
|     DirWalk* dir_walk = dir_walk_alloc(storage); | ||||
|     string_t path; | ||||
|     string_t tmp_new_path; | ||||
|     string_t tmp_old_path; | ||||
|     FileInfo fileinfo; | ||||
|     string_init(path); | ||||
|     string_init(tmp_new_path); | ||||
|     string_init(tmp_old_path); | ||||
| 
 | ||||
|     do { | ||||
|         if((error != FSE_OK) && (error != FSE_EXIST)) break; | ||||
| 
 | ||||
|         if(!dir_walk_open(dir_walk, old_path)) { | ||||
|             error = dir_walk_get_error(dir_walk); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         while(1) { | ||||
|             DirWalkResult res = dir_walk_read(dir_walk, path, &fileinfo); | ||||
| 
 | ||||
|             if(res == DirWalkError) { | ||||
|                 error = dir_walk_get_error(dir_walk); | ||||
|                 break; | ||||
|             } else if(res == DirWalkLast) { | ||||
|                 break; | ||||
|             } else { | ||||
|                 string_set(tmp_old_path, path); | ||||
|                 string_right(path, strlen(old_path)); | ||||
|                 string_printf(tmp_new_path, "%s%s", new_path, string_get_cstr(path)); | ||||
| 
 | ||||
|                 if(fileinfo.flags & FSF_DIRECTORY) { | ||||
|                     if(storage_common_stat(storage, string_get_cstr(tmp_new_path), &fileinfo) == | ||||
|                        FSE_OK) { | ||||
|                         if(fileinfo.flags & FSF_DIRECTORY) { | ||||
|                             error = storage_common_mkdir(storage, string_get_cstr(tmp_new_path)); | ||||
|                         } | ||||
|                     } | ||||
|                 } else { | ||||
|                     error = storage_common_merge( | ||||
|                         storage, string_get_cstr(tmp_old_path), string_get_cstr(tmp_new_path)); | ||||
|                 } | ||||
| 
 | ||||
|                 if(error != FSE_OK) break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } while(false); | ||||
| 
 | ||||
|     string_clear(tmp_new_path); | ||||
|     string_clear(tmp_old_path); | ||||
|     string_clear(path); | ||||
|     dir_walk_free(dir_walk); | ||||
|     return error; | ||||
| } | ||||
| 
 | ||||
| FS_Error storage_common_merge(Storage* storage, const char* old_path, const char* new_path) { | ||||
|     FS_Error error; | ||||
|     const char* new_path_tmp; | ||||
|     string_t new_path_next; | ||||
|     string_init(new_path_next); | ||||
| 
 | ||||
|     FileInfo fileinfo; | ||||
|     error = storage_common_stat(storage, old_path, &fileinfo); | ||||
| 
 | ||||
|     if(error == FSE_OK) { | ||||
|         if(fileinfo.flags & FSF_DIRECTORY) { | ||||
|             error = storage_merge_recursive(storage, old_path, new_path); | ||||
|         } else { | ||||
|             error = storage_common_stat(storage, new_path, &fileinfo); | ||||
|             if(error == FSE_OK) { | ||||
|                 string_set_str(new_path_next, new_path); | ||||
|                 string_t dir_path; | ||||
|                 string_t filename; | ||||
|                 char extension[MAX_EXT_LEN]; | ||||
| 
 | ||||
|                 string_init(dir_path); | ||||
|                 string_init(filename); | ||||
| 
 | ||||
|                 path_extract_filename(new_path_next, filename, true); | ||||
|                 path_extract_dirname(new_path, dir_path); | ||||
|                 path_extract_extension(new_path_next, extension, MAX_EXT_LEN); | ||||
| 
 | ||||
|                 storage_get_next_filename( | ||||
|                     storage, | ||||
|                     string_get_cstr(dir_path), | ||||
|                     string_get_cstr(filename), | ||||
|                     extension, | ||||
|                     new_path_next, | ||||
|                     255); | ||||
|                 string_cat_printf(dir_path, "/%s%s", string_get_cstr(new_path_next), extension); | ||||
|                 string_set(new_path_next, dir_path); | ||||
| 
 | ||||
|                 string_clear(dir_path); | ||||
|                 string_clear(filename); | ||||
|                 new_path_tmp = string_get_cstr(new_path_next); | ||||
|             } else { | ||||
|                 new_path_tmp = new_path; | ||||
|             } | ||||
|             Stream* stream_from = file_stream_alloc(storage); | ||||
|             Stream* stream_to = file_stream_alloc(storage); | ||||
| 
 | ||||
|             do { | ||||
|                 if(!file_stream_open(stream_from, old_path, FSAM_READ, FSOM_OPEN_EXISTING)) break; | ||||
|                 if(!file_stream_open(stream_to, new_path_tmp, FSAM_WRITE, FSOM_CREATE_NEW)) break; | ||||
|                 stream_copy_full(stream_from, stream_to); | ||||
|             } while(false); | ||||
| 
 | ||||
|             error = file_stream_get_error(stream_from); | ||||
|             if(error == FSE_OK) { | ||||
|                 error = file_stream_get_error(stream_to); | ||||
|             } | ||||
| 
 | ||||
|             stream_free(stream_from); | ||||
|             stream_free(stream_to); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     string_clear(new_path_next); | ||||
| 
 | ||||
|     return error; | ||||
| } | ||||
| 
 | ||||
| FS_Error storage_common_mkdir(Storage* storage, const char* path) { | ||||
|     S_API_PROLOGUE; | ||||
|     S_API_DATA_PATH; | ||||
|  | ||||
							
								
								
									
										19
									
								
								applications/storage_move_to_sd/application.fam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								applications/storage_move_to_sd/application.fam
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| App( | ||||
|     appid="storage_move_to_sd", | ||||
|     name="StorageMoveToSd", | ||||
|     apptype=FlipperAppType.SYSTEM, | ||||
|     entry_point="storage_move_to_sd_app", | ||||
|     requires=["gui","storage"], | ||||
|     provides=["storage_move_to_sd_start"], | ||||
|     stack_size=2 * 1024, | ||||
|     order=30, | ||||
| ) | ||||
| 
 | ||||
| App( | ||||
|     appid="storage_move_to_sd_start", | ||||
|     apptype=FlipperAppType.STARTUP, | ||||
|     entry_point="storage_move_to_sd_start", | ||||
|     requires=["storage"], | ||||
|     order=120, | ||||
| ) | ||||
| 
 | ||||
| @ -0,0 +1,30 @@ | ||||
| #include "storage_move_to_sd_scene.h" | ||||
| 
 | ||||
| // Generate scene on_enter handlers array
 | ||||
| #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, | ||||
| void (*const storage_move_to_sd_on_enter_handlers[])(void*) = { | ||||
| #include "storage_move_to_sd_scene_config.h" | ||||
| }; | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Generate scene on_event handlers array
 | ||||
| #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, | ||||
| bool (*const storage_move_to_sd_on_event_handlers[])(void* context, SceneManagerEvent event) = { | ||||
| #include "storage_move_to_sd_scene_config.h" | ||||
| }; | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Generate scene on_exit handlers array
 | ||||
| #define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, | ||||
| void (*const storage_move_to_sd_on_exit_handlers[])(void* context) = { | ||||
| #include "storage_move_to_sd_scene_config.h" | ||||
| }; | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Initialize scene handlers configuration structure
 | ||||
| const SceneManagerHandlers storage_move_to_sd_scene_handlers = { | ||||
|     .on_enter_handlers = storage_move_to_sd_on_enter_handlers, | ||||
|     .on_event_handlers = storage_move_to_sd_on_event_handlers, | ||||
|     .on_exit_handlers = storage_move_to_sd_on_exit_handlers, | ||||
|     .scene_num = StorageMoveToSdSceneNum, | ||||
| }; | ||||
| @ -0,0 +1,29 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <gui/scene_manager.h> | ||||
| 
 | ||||
| // Generate scene id and total number
 | ||||
| #define ADD_SCENE(prefix, name, id) StorageMoveToSd##id, | ||||
| typedef enum { | ||||
| #include "storage_move_to_sd_scene_config.h" | ||||
|     StorageMoveToSdSceneNum, | ||||
| } StorageMoveToSdScene; | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| extern const SceneManagerHandlers storage_move_to_sd_scene_handlers; | ||||
| 
 | ||||
| // Generate scene on_enter handlers declaration
 | ||||
| #define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); | ||||
| #include "storage_move_to_sd_scene_config.h" | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Generate scene on_event handlers declaration
 | ||||
| #define ADD_SCENE(prefix, name, id) \ | ||||
|     bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); | ||||
| #include "storage_move_to_sd_scene_config.h" | ||||
| #undef ADD_SCENE | ||||
| 
 | ||||
| // Generate scene on_exit handlers declaration
 | ||||
| #define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); | ||||
| #include "storage_move_to_sd_scene_config.h" | ||||
| #undef ADD_SCENE | ||||
| @ -0,0 +1,2 @@ | ||||
| ADD_SCENE(storage_move_to_sd, confirm, Confirm) | ||||
| ADD_SCENE(storage_move_to_sd, progress, Progress) | ||||
| @ -0,0 +1,70 @@ | ||||
| #include "../storage_move_to_sd.h" | ||||
| #include "gui/canvas.h" | ||||
| #include "gui/modules/widget_elements/widget_element_i.h" | ||||
| #include "storage/storage.h" | ||||
| 
 | ||||
| static void storage_move_to_sd_scene_confirm_widget_callback( | ||||
|     GuiButtonType result, | ||||
|     InputType type, | ||||
|     void* context) { | ||||
|     StorageMoveToSd* app = context; | ||||
|     furi_assert(app); | ||||
|     if(type == InputTypeShort) { | ||||
|         if(result == GuiButtonTypeRight) { | ||||
|             view_dispatcher_send_custom_event(app->view_dispatcher, MoveToSdCustomEventConfirm); | ||||
|         } else if(result == GuiButtonTypeLeft) { | ||||
|             view_dispatcher_send_custom_event(app->view_dispatcher, MoveToSdCustomEventExit); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void storage_move_to_sd_scene_confirm_on_enter(void* context) { | ||||
|     StorageMoveToSd* app = context; | ||||
| 
 | ||||
|     widget_add_button_element( | ||||
|         app->widget, | ||||
|         GuiButtonTypeLeft, | ||||
|         "Cancel", | ||||
|         storage_move_to_sd_scene_confirm_widget_callback, | ||||
|         app); | ||||
|     widget_add_button_element( | ||||
|         app->widget, | ||||
|         GuiButtonTypeRight, | ||||
|         "Confirm", | ||||
|         storage_move_to_sd_scene_confirm_widget_callback, | ||||
|         app); | ||||
| 
 | ||||
|     widget_add_string_element( | ||||
|         app->widget, 64, 10, AlignCenter, AlignCenter, FontPrimary, "SD card inserted"); | ||||
|     widget_add_string_multiline_element( | ||||
|         app->widget, | ||||
|         64, | ||||
|         32, | ||||
|         AlignCenter, | ||||
|         AlignCenter, | ||||
|         FontSecondary, | ||||
|         "Move data from\ninternal storage to SD card?"); | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(app->view_dispatcher, StorageMoveToSdViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool storage_move_to_sd_scene_confirm_on_event(void* context, SceneManagerEvent event) { | ||||
|     StorageMoveToSd* app = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == MoveToSdCustomEventConfirm) { | ||||
|             scene_manager_next_scene(app->scene_manager, StorageMoveToSdProgress); | ||||
|             consumed = true; | ||||
|         } else if(event.event == MoveToSdCustomEventExit) { | ||||
|             view_dispatcher_stop(app->view_dispatcher); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void storage_move_to_sd_scene_confirm_on_exit(void* context) { | ||||
|     StorageMoveToSd* app = context; | ||||
|     widget_reset(app->widget); | ||||
| } | ||||
| @ -0,0 +1,32 @@ | ||||
| #include "../storage_move_to_sd.h" | ||||
| #include "cmsis_os2.h" | ||||
| 
 | ||||
| void storage_move_to_sd_scene_progress_on_enter(void* context) { | ||||
|     StorageMoveToSd* app = context; | ||||
| 
 | ||||
|     widget_add_string_element( | ||||
|         app->widget, 64, 10, AlignCenter, AlignCenter, FontPrimary, "Moving..."); | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(app->view_dispatcher, StorageMoveToSdViewWidget); | ||||
| 
 | ||||
|     storage_move_to_sd_perform(); | ||||
|     view_dispatcher_send_custom_event(app->view_dispatcher, MoveToSdCustomEventExit); | ||||
| } | ||||
| 
 | ||||
| bool storage_move_to_sd_scene_progress_on_event(void* context, SceneManagerEvent event) { | ||||
|     StorageMoveToSd* app = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         view_dispatcher_stop(app->view_dispatcher); | ||||
|     } else if(event.type == SceneManagerEventTypeBack) { | ||||
|         consumed = true; | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void storage_move_to_sd_scene_progress_on_exit(void* context) { | ||||
|     StorageMoveToSd* app = context; | ||||
|     widget_reset(app->widget); | ||||
| } | ||||
							
								
								
									
										177
									
								
								applications/storage_move_to_sd/storage_move_to_sd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								applications/storage_move_to_sd/storage_move_to_sd.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,177 @@ | ||||
| #include "storage_move_to_sd.h" | ||||
| #include "cmsis_os2.h" | ||||
| #include "furi/common_defines.h" | ||||
| #include "furi/log.h" | ||||
| #include "loader/loader.h" | ||||
| #include "m-string.h" | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #define TAG "MoveToSd" | ||||
| 
 | ||||
| #define MOVE_SRC "/int" | ||||
| #define MOVE_DST "/ext" | ||||
| 
 | ||||
| static const char* app_dirs[] = { | ||||
|     "subghz", | ||||
|     "lfrfid", | ||||
|     "nfc", | ||||
|     "infrared", | ||||
|     "ibutton", | ||||
|     "badusb", | ||||
| }; | ||||
| 
 | ||||
| bool storage_move_to_sd_perform(void) { | ||||
|     Storage* storage = furi_record_open("storage"); | ||||
|     string_t path_src; | ||||
|     string_t path_dst; | ||||
|     string_init(path_src); | ||||
|     string_init(path_dst); | ||||
| 
 | ||||
|     for(uint32_t i = 0; i < COUNT_OF(app_dirs); i++) { | ||||
|         string_printf(path_src, "%s/%s", MOVE_SRC, app_dirs[i]); | ||||
|         string_printf(path_dst, "%s/%s", MOVE_DST, app_dirs[i]); | ||||
|         storage_common_merge(storage, string_get_cstr(path_src), string_get_cstr(path_dst)); | ||||
|         storage_simply_remove_recursive(storage, string_get_cstr(path_src)); | ||||
|     } | ||||
| 
 | ||||
|     string_clear(path_src); | ||||
|     string_clear(path_dst); | ||||
| 
 | ||||
|     furi_record_close("storage"); | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| static bool storage_move_to_sd_check(void) { | ||||
|     Storage* storage = furi_record_open("storage"); | ||||
| 
 | ||||
|     FileInfo file_info; | ||||
|     bool state = false; | ||||
|     string_t path; | ||||
|     string_init(path); | ||||
| 
 | ||||
|     for(uint32_t i = 0; i < COUNT_OF(app_dirs); i++) { | ||||
|         string_printf(path, "%s/%s", MOVE_SRC, app_dirs[i]); | ||||
|         if(storage_common_stat(storage, string_get_cstr(path), &file_info) == FSE_OK) { | ||||
|             if((file_info.flags & FSF_DIRECTORY) != 0) { | ||||
|                 state = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     string_clear(path); | ||||
| 
 | ||||
|     furi_record_close("storage"); | ||||
| 
 | ||||
|     return state; | ||||
| } | ||||
| 
 | ||||
| static bool storage_move_to_sd_custom_event_callback(void* context, uint32_t event) { | ||||
|     furi_assert(context); | ||||
|     StorageMoveToSd* app = context; | ||||
|     return scene_manager_handle_custom_event(app->scene_manager, event); | ||||
| } | ||||
| 
 | ||||
| static bool storage_move_to_sd_back_event_callback(void* context) { | ||||
|     furi_assert(context); | ||||
|     StorageMoveToSd* app = context; | ||||
|     return scene_manager_handle_back_event(app->scene_manager); | ||||
| } | ||||
| 
 | ||||
| static void storage_move_to_sd_unmount_callback(const void* message, void* context) { | ||||
|     StorageMoveToSd* app = context; | ||||
|     furi_assert(app); | ||||
|     const StorageEvent* storage_event = message; | ||||
| 
 | ||||
|     if((storage_event->type == StorageEventTypeCardUnmount) || | ||||
|        (storage_event->type == StorageEventTypeCardMountError)) { | ||||
|         view_dispatcher_send_custom_event(app->view_dispatcher, MoveToSdCustomEventExit); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static StorageMoveToSd* storage_move_to_sd_alloc() { | ||||
|     StorageMoveToSd* app = malloc(sizeof(StorageMoveToSd)); | ||||
| 
 | ||||
|     app->gui = furi_record_open("gui"); | ||||
|     app->notifications = furi_record_open("notification"); | ||||
| 
 | ||||
|     app->view_dispatcher = view_dispatcher_alloc(); | ||||
|     app->scene_manager = scene_manager_alloc(&storage_move_to_sd_scene_handlers, app); | ||||
| 
 | ||||
|     view_dispatcher_enable_queue(app->view_dispatcher); | ||||
|     view_dispatcher_set_event_callback_context(app->view_dispatcher, app); | ||||
| 
 | ||||
|     view_dispatcher_set_custom_event_callback( | ||||
|         app->view_dispatcher, storage_move_to_sd_custom_event_callback); | ||||
|     view_dispatcher_set_navigation_event_callback( | ||||
|         app->view_dispatcher, storage_move_to_sd_back_event_callback); | ||||
| 
 | ||||
|     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); | ||||
| 
 | ||||
|     app->widget = widget_alloc(); | ||||
|     view_dispatcher_add_view( | ||||
|         app->view_dispatcher, StorageMoveToSdViewWidget, widget_get_view(app->widget)); | ||||
| 
 | ||||
|     scene_manager_next_scene(app->scene_manager, StorageMoveToSdConfirm); | ||||
| 
 | ||||
|     Storage* storage = furi_record_open("storage"); | ||||
|     app->sub = furi_pubsub_subscribe( | ||||
|         storage_get_pubsub(storage), storage_move_to_sd_unmount_callback, app); | ||||
|     furi_record_close("storage"); | ||||
| 
 | ||||
|     return app; | ||||
| } | ||||
| 
 | ||||
| static void storage_move_to_sd_free(StorageMoveToSd* app) { | ||||
|     Storage* storage = furi_record_open("storage"); | ||||
|     furi_pubsub_unsubscribe(storage_get_pubsub(storage), app->sub); | ||||
|     furi_record_close("storage"); | ||||
|     furi_record_close("notification"); | ||||
| 
 | ||||
|     view_dispatcher_remove_view(app->view_dispatcher, StorageMoveToSdViewWidget); | ||||
|     widget_free(app->widget); | ||||
|     view_dispatcher_free(app->view_dispatcher); | ||||
|     scene_manager_free(app->scene_manager); | ||||
| 
 | ||||
|     furi_record_close("gui"); | ||||
| 
 | ||||
|     free(app); | ||||
| } | ||||
| 
 | ||||
| int32_t storage_move_to_sd_app(void* p) { | ||||
|     UNUSED(p); | ||||
| 
 | ||||
|     if(storage_move_to_sd_check()) { | ||||
|         StorageMoveToSd* app = storage_move_to_sd_alloc(); | ||||
|         notification_message(app->notifications, &sequence_display_backlight_on); | ||||
|         view_dispatcher_run(app->view_dispatcher); | ||||
|         storage_move_to_sd_free(app); | ||||
|     } else { | ||||
|         FURI_LOG_I(TAG, "Nothing to move"); | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static void storage_move_to_sd_mount_callback(const void* message, void* context) { | ||||
|     UNUSED(context); | ||||
| 
 | ||||
|     const StorageEvent* storage_event = message; | ||||
| 
 | ||||
|     if(storage_event->type == StorageEventTypeCardMount) { | ||||
|         Loader* loader = furi_record_open("loader"); | ||||
|         loader_start(loader, "StorageMoveToSd", NULL); | ||||
|         furi_record_close("loader"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int32_t storage_move_to_sd_start(void* p) { | ||||
|     UNUSED(p); | ||||
|     Storage* storage = furi_record_open("storage"); | ||||
| 
 | ||||
|     furi_pubsub_subscribe(storage_get_pubsub(storage), storage_move_to_sd_mount_callback, NULL); | ||||
| 
 | ||||
|     furi_record_close("storage"); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										49
									
								
								applications/storage_move_to_sd/storage_move_to_sd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								applications/storage_move_to_sd/storage_move_to_sd.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| #pragma once | ||||
| #include "gui/modules/widget_elements/widget_element_i.h" | ||||
| #include <furi.h> | ||||
| #include <gui/gui.h> | ||||
| #include <gui/view.h> | ||||
| #include <gui/view_dispatcher.h> | ||||
| #include <gui/scene_manager.h> | ||||
| #include <notification/notification_messages.h> | ||||
| 
 | ||||
| #include <gui/modules/widget.h> | ||||
| #include <gui/modules/popup.h> | ||||
| 
 | ||||
| #include <storage/storage.h> | ||||
| #include <storage/storage_sd_api.h> | ||||
| 
 | ||||
| #include "scenes/storage_move_to_sd_scene.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| typedef enum { | ||||
|     MoveToSdCustomEventExit, | ||||
|     MoveToSdCustomEventConfirm, | ||||
| } MoveToSdCustomEvent; | ||||
| 
 | ||||
| typedef struct { | ||||
|     // records
 | ||||
|     Gui* gui; | ||||
|     Widget* widget; | ||||
|     NotificationApp* notifications; | ||||
| 
 | ||||
|     // view managment
 | ||||
|     SceneManager* scene_manager; | ||||
|     ViewDispatcher* view_dispatcher; | ||||
| 
 | ||||
|     FuriPubSubSubscription* sub; | ||||
| 
 | ||||
| } StorageMoveToSd; | ||||
| 
 | ||||
| typedef enum { | ||||
|     StorageMoveToSdViewWidget, | ||||
| } StorageMoveToSdView; | ||||
| 
 | ||||
| bool storage_move_to_sd_perform(void); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| @ -67,6 +67,7 @@ FIRMWARE_APPS = { | ||||
|         # Apps | ||||
|         "basic_apps", | ||||
|         "updater_app", | ||||
|         "storage_move_to_sd", | ||||
|         "archive", | ||||
|         # Settings | ||||
|         "passport", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Nikolay Minaylov
						Nikolay Minaylov