[FL-2491] File browser GUI module (#1237)

* File browser module and test app
* nfc: Add support for saved files in subdirectories
* nfc: Use helper function to get shadow path when loading data
* File browser dialog integration pt.1
* File browser dialog integration pt.2
* Gui,Dialogs: drop file select
* Correct use of dynamic string_t(string_ptr)

Co-authored-by: Yukai Li <yukaili.geek@gmail.com>
Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
Nikolay Minaylov
2022-05-27 14:19:21 +03:00
committed by GitHub
parent 533f12af15
commit 79920a3522
82 changed files with 2025 additions and 1007 deletions

View File

@@ -1,7 +1,8 @@
#include "ibutton.h"
#include "assets_icons.h"
#include "ibutton_i.h"
#include "ibutton/scenes/ibutton_scene.h"
#include "m-string.h"
#include <toolbox/path.h>
#include <flipper_format/flipper_format.h>
@@ -85,6 +86,8 @@ void ibutton_tick_event_callback(void* context) {
iButton* ibutton_alloc() {
iButton* ibutton = malloc(sizeof(iButton));
string_init(ibutton->file_path);
ibutton->scene_manager = scene_manager_alloc(&ibutton_scene_handlers, ibutton);
ibutton->view_dispatcher = view_dispatcher_alloc();
@@ -176,49 +179,28 @@ void ibutton_free(iButton* ibutton) {
ibutton_worker_free(ibutton->key_worker);
ibutton_key_free(ibutton->key);
string_clear(ibutton->file_path);
free(ibutton);
}
bool ibutton_file_select(iButton* ibutton) {
bool success = dialog_file_select_show(
bool success = dialog_file_browser_show(
ibutton->dialogs,
IBUTTON_APP_FOLDER,
ibutton->file_path,
ibutton->file_path,
IBUTTON_APP_EXTENSION,
ibutton->file_name,
IBUTTON_FILE_NAME_SIZE,
ibutton_key_get_name_p(ibutton->key));
true,
&I_ibutt_10px,
true);
if(success) {
string_t key_str;
string_init_printf(
key_str, "%s/%s%s", IBUTTON_APP_FOLDER, ibutton->file_name, IBUTTON_APP_EXTENSION);
success = ibutton_load_key_data(ibutton, key_str);
if(success) {
ibutton_key_set_name(ibutton->key, ibutton->file_name);
}
string_clear(key_str);
success = ibutton_load_key_data(ibutton, ibutton->file_path);
}
return success;
}
bool ibutton_load_key(iButton* ibutton, const char* key_name) {
string_t key_path;
string_init_set_str(key_path, key_name);
const bool success = ibutton_load_key_data(ibutton, key_path);
if(success) {
path_extract_filename_no_ext(key_name, key_path);
ibutton_key_set_name(ibutton->key, string_get_cstr(key_path));
}
string_clear(key_path);
return success;
}
bool ibutton_save_key(iButton* ibutton, const char* key_name) {
// Create ibutton directory if necessary
ibutton_make_app_folder(ibutton);
@@ -226,27 +208,22 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) {
FlipperFormat* file = flipper_format_file_alloc(ibutton->storage);
iButtonKey* key = ibutton->key;
string_t key_file_name;
bool result = false;
string_init(key_file_name);
do {
// First remove key if it was saved (we rename the key)
if(!ibutton_delete_key(ibutton)) break;
// Save the key
ibutton_key_set_name(key, key_name);
ibutton_delete_key(ibutton);
// Set full file name, for new key
string_printf(
key_file_name,
"%s/%s%s",
IBUTTON_APP_FOLDER,
ibutton_key_get_name_p(key),
IBUTTON_APP_EXTENSION);
if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
size_t filename_start = string_search_rchar(ibutton->file_path, '/');
string_left(ibutton->file_path, filename_start);
}
string_cat_printf(ibutton->file_path, "/%s%s", key_name, IBUTTON_APP_EXTENSION);
// Open file for write
if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break;
if(!flipper_format_file_open_always(file, string_get_cstr(ibutton->file_path))) break;
// Write header
if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break;
@@ -271,8 +248,6 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) {
flipper_format_free(file);
string_clear(key_file_name);
if(!result) {
dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file");
}
@@ -281,17 +256,8 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) {
}
bool ibutton_delete_key(iButton* ibutton) {
string_t file_name;
bool result = false;
string_init_printf(
file_name,
"%s/%s%s",
IBUTTON_APP_FOLDER,
ibutton_key_get_name_p(ibutton->key),
IBUTTON_APP_EXTENSION);
result = storage_simply_remove(ibutton->storage, string_get_cstr(file_name));
string_clear(file_name);
result = storage_simply_remove(ibutton->storage, string_get_cstr(ibutton->file_path));
return result;
}
@@ -335,8 +301,17 @@ int32_t ibutton_app(void* p) {
ibutton_make_app_folder(ibutton);
if(p && ibutton_load_key(ibutton, (const char*)p)) {
// TODO: Display an error if the key from p could not be loaded
bool key_loaded = false;
if(p) {
string_set_str(ibutton->file_path, (const char*)p);
if(ibutton_load_key_data(ibutton, ibutton->file_path)) {
key_loaded = true;
// TODO: Display an error if the key from p could not be loaded
}
}
if(key_loaded) {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
} else {
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart);