[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:
@@ -1,4 +1,6 @@
|
||||
#include "nfc_device.h"
|
||||
#include "assets_icons.h"
|
||||
#include "m-string.h"
|
||||
#include "nfc_types.h"
|
||||
|
||||
#include <toolbox/path.h>
|
||||
@@ -14,6 +16,7 @@ NfcDevice* nfc_device_alloc() {
|
||||
NfcDevice* nfc_dev = malloc(sizeof(NfcDevice));
|
||||
nfc_dev->storage = furi_record_open("storage");
|
||||
nfc_dev->dialogs = furi_record_open("dialogs");
|
||||
string_init(nfc_dev->load_path);
|
||||
return nfc_dev;
|
||||
}
|
||||
|
||||
@@ -22,6 +25,7 @@ void nfc_device_free(NfcDevice* nfc_dev) {
|
||||
nfc_device_clear(nfc_dev);
|
||||
furi_record_close("storage");
|
||||
furi_record_close("dialogs");
|
||||
string_clear(nfc_dev->load_path);
|
||||
free(nfc_dev);
|
||||
}
|
||||
|
||||
@@ -730,11 +734,24 @@ void nfc_device_set_name(NfcDevice* dev, const char* name) {
|
||||
strlcpy(dev->dev_name, name, NFC_DEV_NAME_MAX_LEN);
|
||||
}
|
||||
|
||||
static void nfc_device_get_path_without_ext(string_t orig_path, string_t shadow_path) {
|
||||
// TODO: this won't work if there is ".nfc" anywhere in the path other than
|
||||
// at the end
|
||||
size_t ext_start = string_search_str(orig_path, NFC_APP_EXTENSION);
|
||||
string_set_n(shadow_path, orig_path, 0, ext_start);
|
||||
}
|
||||
|
||||
static void nfc_device_get_shadow_path(string_t orig_path, string_t shadow_path) {
|
||||
nfc_device_get_path_without_ext(orig_path, shadow_path);
|
||||
string_cat_printf(shadow_path, "%s", NFC_APP_SHADOW_EXTENSION);
|
||||
}
|
||||
|
||||
static bool nfc_device_save_file(
|
||||
NfcDevice* dev,
|
||||
const char* dev_name,
|
||||
const char* folder,
|
||||
const char* extension) {
|
||||
const char* extension,
|
||||
bool use_load_path) {
|
||||
furi_assert(dev);
|
||||
|
||||
bool saved = false;
|
||||
@@ -744,10 +761,19 @@ static bool nfc_device_save_file(
|
||||
string_init(temp_str);
|
||||
|
||||
do {
|
||||
// Create nfc directory if necessary
|
||||
if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break;
|
||||
// First remove nfc device file if it was saved
|
||||
string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
|
||||
if(use_load_path && !string_empty_p(dev->load_path)) {
|
||||
// Get directory name
|
||||
path_extract_dirname(string_get_cstr(dev->load_path), temp_str);
|
||||
// Create nfc directory if necessary
|
||||
if(!storage_simply_mkdir(dev->storage, string_get_cstr(temp_str))) break;
|
||||
// Make path to file to save
|
||||
string_cat_printf(temp_str, "/%s%s", dev_name, extension);
|
||||
} else {
|
||||
// Create nfc directory if necessary
|
||||
if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break;
|
||||
// First remove nfc device file if it was saved
|
||||
string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
|
||||
}
|
||||
// Open file
|
||||
if(!flipper_format_file_open_always(file, string_get_cstr(temp_str))) break;
|
||||
// Write header
|
||||
@@ -786,12 +812,12 @@ static bool nfc_device_save_file(
|
||||
}
|
||||
|
||||
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
|
||||
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_EXTENSION);
|
||||
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_EXTENSION, true);
|
||||
}
|
||||
|
||||
bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) {
|
||||
dev->shadow_file_exist = true;
|
||||
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION);
|
||||
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION, true);
|
||||
}
|
||||
|
||||
static bool nfc_device_load_data(NfcDevice* dev, string_t path) {
|
||||
@@ -805,9 +831,7 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path) {
|
||||
|
||||
do {
|
||||
// Check existance of shadow file
|
||||
size_t ext_start = string_search_str(path, NFC_APP_EXTENSION);
|
||||
string_set_n(temp_str, path, 0, ext_start);
|
||||
string_cat_printf(temp_str, "%s", NFC_APP_SHADOW_EXTENSION);
|
||||
nfc_device_get_shadow_path(path, temp_str);
|
||||
dev->shadow_file_exist =
|
||||
storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK;
|
||||
// Open shadow file if it exists. If not - open original
|
||||
@@ -864,15 +888,16 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
|
||||
furi_assert(file_path);
|
||||
|
||||
// Load device data
|
||||
string_t path;
|
||||
string_init_set_str(path, file_path);
|
||||
bool dev_load = nfc_device_load_data(dev, path);
|
||||
string_set_str(dev->load_path, file_path);
|
||||
bool dev_load = nfc_device_load_data(dev, dev->load_path);
|
||||
if(dev_load) {
|
||||
// Set device name
|
||||
path_extract_filename_no_ext(file_path, path);
|
||||
nfc_device_set_name(dev, string_get_cstr(path));
|
||||
string_t filename;
|
||||
string_init(filename);
|
||||
path_extract_filename_no_ext(file_path, filename);
|
||||
nfc_device_set_name(dev, string_get_cstr(filename));
|
||||
string_clear(filename);
|
||||
}
|
||||
string_clear(path);
|
||||
|
||||
return dev_load;
|
||||
}
|
||||
@@ -880,23 +905,19 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) {
|
||||
bool nfc_file_select(NfcDevice* dev) {
|
||||
furi_assert(dev);
|
||||
|
||||
// Input events and views are managed by file_select
|
||||
bool res = dialog_file_select_show(
|
||||
dev->dialogs,
|
||||
NFC_APP_FOLDER,
|
||||
NFC_APP_EXTENSION,
|
||||
dev->file_name,
|
||||
sizeof(dev->file_name),
|
||||
dev->dev_name);
|
||||
// Input events and views are managed by file_browser
|
||||
bool res = dialog_file_browser_show(
|
||||
dev->dialogs, dev->load_path, dev->load_path, NFC_APP_EXTENSION, true, &I_Nfc_10px, true);
|
||||
if(res) {
|
||||
string_t dev_str;
|
||||
// Get key file path
|
||||
string_init_printf(dev_str, "%s/%s%s", NFC_APP_FOLDER, dev->file_name, NFC_APP_EXTENSION);
|
||||
res = nfc_device_load_data(dev, dev_str);
|
||||
string_t filename;
|
||||
string_init(filename);
|
||||
path_extract_filename(dev->load_path, filename, true);
|
||||
strncpy(dev->dev_name, string_get_cstr(filename), NFC_DEV_NAME_MAX_LEN);
|
||||
res = nfc_device_load_data(dev, dev->load_path);
|
||||
if(res) {
|
||||
nfc_device_set_name(dev, dev->file_name);
|
||||
nfc_device_set_name(dev, dev->dev_name);
|
||||
}
|
||||
string_clear(dev_str);
|
||||
string_clear(filename);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -914,9 +935,10 @@ void nfc_device_clear(NfcDevice* dev) {
|
||||
nfc_device_data_clear(&dev->dev_data);
|
||||
memset(&dev->dev_data, 0, sizeof(dev->dev_data));
|
||||
dev->format = NfcDeviceSaveFormatUid;
|
||||
string_set_str(dev->load_path, NFC_APP_FOLDER);
|
||||
}
|
||||
|
||||
bool nfc_device_delete(NfcDevice* dev) {
|
||||
bool nfc_device_delete(NfcDevice* dev, bool use_load_path) {
|
||||
furi_assert(dev);
|
||||
|
||||
bool deleted = false;
|
||||
@@ -925,12 +947,20 @@ bool nfc_device_delete(NfcDevice* dev) {
|
||||
|
||||
do {
|
||||
// Delete original file
|
||||
string_init_printf(file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION);
|
||||
if(use_load_path && !string_empty_p(dev->load_path)) {
|
||||
string_set(file_path, dev->load_path);
|
||||
} else {
|
||||
string_printf(file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION);
|
||||
}
|
||||
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break;
|
||||
// Delete shadow file if it exists
|
||||
if(dev->shadow_file_exist) {
|
||||
string_printf(
|
||||
file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION);
|
||||
if(use_load_path && !string_empty_p(dev->load_path)) {
|
||||
nfc_device_get_shadow_path(dev->load_path, file_path);
|
||||
} else {
|
||||
string_printf(
|
||||
file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION);
|
||||
}
|
||||
if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break;
|
||||
}
|
||||
deleted = true;
|
||||
@@ -944,19 +974,29 @@ bool nfc_device_delete(NfcDevice* dev) {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
bool nfc_device_restore(NfcDevice* dev) {
|
||||
bool nfc_device_restore(NfcDevice* dev, bool use_load_path) {
|
||||
furi_assert(dev);
|
||||
furi_assert(dev->shadow_file_exist);
|
||||
|
||||
bool restored = false;
|
||||
string_t path;
|
||||
|
||||
string_init(path);
|
||||
|
||||
do {
|
||||
string_init_printf(
|
||||
path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION);
|
||||
if(use_load_path && !string_empty_p(dev->load_path)) {
|
||||
nfc_device_get_shadow_path(dev->load_path, path);
|
||||
} else {
|
||||
string_printf(
|
||||
path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION);
|
||||
}
|
||||
if(!storage_simply_remove(dev->storage, string_get_cstr(path))) break;
|
||||
dev->shadow_file_exist = false;
|
||||
string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION);
|
||||
if(use_load_path && !string_empty_p(dev->load_path)) {
|
||||
string_set(path, dev->load_path);
|
||||
} else {
|
||||
string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION);
|
||||
}
|
||||
if(!nfc_device_load_data(dev, path)) break;
|
||||
restored = true;
|
||||
} while(0);
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include <lib/nfc_protocols/mifare_desfire.h>
|
||||
|
||||
#define NFC_DEV_NAME_MAX_LEN 22
|
||||
#define NFC_FILE_NAME_MAX_LEN 120
|
||||
#define NFC_READER_DATA_MAX_SIZE 64
|
||||
|
||||
#define NFC_APP_FOLDER "/any/nfc"
|
||||
@@ -57,7 +56,7 @@ typedef struct {
|
||||
DialogsApp* dialogs;
|
||||
NfcDeviceData dev_data;
|
||||
char dev_name[NFC_DEV_NAME_MAX_LEN + 1];
|
||||
char file_name[NFC_FILE_NAME_MAX_LEN];
|
||||
string_t load_path;
|
||||
NfcDeviceSaveFormat format;
|
||||
bool shadow_file_exist;
|
||||
} NfcDevice;
|
||||
@@ -80,6 +79,6 @@ void nfc_device_data_clear(NfcDeviceData* dev);
|
||||
|
||||
void nfc_device_clear(NfcDevice* dev);
|
||||
|
||||
bool nfc_device_delete(NfcDevice* dev);
|
||||
bool nfc_device_delete(NfcDevice* dev, bool use_load_path);
|
||||
|
||||
bool nfc_device_restore(NfcDevice* dev);
|
||||
bool nfc_device_restore(NfcDevice* dev, bool use_load_path);
|
||||
|
@@ -73,7 +73,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
return scene_manager_previous_scene(nfc->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
if(nfc_device_delete(nfc->dev)) {
|
||||
if(nfc_device_delete(nfc->dev, true)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
|
19
applications/nfc/scenes/nfc_scene_save_name.c
Executable file → Normal file
19
applications/nfc/scenes/nfc_scene_save_name.c
Executable file → Normal file
@@ -1,6 +1,8 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "m-string.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <gui/modules/validators.h>
|
||||
#include <toolbox/path.h>
|
||||
|
||||
void nfc_scene_save_name_text_input_callback(void* context) {
|
||||
Nfc* nfc = context;
|
||||
@@ -29,11 +31,22 @@ void nfc_scene_save_name_on_enter(void* context) {
|
||||
NFC_DEV_NAME_MAX_LEN,
|
||||
dev_name_empty);
|
||||
|
||||
ValidatorIsFile* validator_is_file =
|
||||
validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION, nfc->dev->dev_name);
|
||||
string_t folder_path;
|
||||
string_init(folder_path);
|
||||
|
||||
if(string_end_with_str_p(nfc->dev->load_path, NFC_APP_EXTENSION)) {
|
||||
path_extract_dirname(string_get_cstr(nfc->dev->load_path), folder_path);
|
||||
} else {
|
||||
string_set_str(folder_path, NFC_APP_FOLDER);
|
||||
}
|
||||
|
||||
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
|
||||
string_get_cstr(folder_path), NFC_APP_EXTENSION, nfc->dev->dev_name);
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput);
|
||||
|
||||
string_clear(folder_path);
|
||||
}
|
||||
|
||||
bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
@@ -43,7 +56,7 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == NfcCustomEventTextInputDone) {
|
||||
if(strcmp(nfc->dev->dev_name, "")) {
|
||||
nfc_device_delete(nfc->dev);
|
||||
nfc_device_delete(nfc->dev, true);
|
||||
}
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) {
|
||||
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
|
||||
|
@@ -30,9 +30,6 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneCardMenu)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneCardMenu);
|
||||
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) {
|
||||
consumed = scene_manager_search_and_switch_to_another_scene(
|
||||
nfc->scene_manager, NfcSceneFileSelect);
|
||||
} else if(scene_manager_has_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMifareDesfireMenu)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
|
@@ -78,7 +78,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexRestoreOriginal) {
|
||||
if(!nfc_device_restore(nfc->dev)) {
|
||||
if(!nfc_device_restore(nfc->dev, true)) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneStart);
|
||||
} else {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "m-string.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexNFCA4,
|
||||
@@ -16,6 +17,7 @@ void nfc_scene_set_type_on_enter(void* context) {
|
||||
Submenu* submenu = nfc->submenu;
|
||||
// Clear device name
|
||||
nfc_device_set_name(nfc->dev, "");
|
||||
string_set_str(nfc->dev->load_path, "");
|
||||
submenu_add_item(
|
||||
submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc);
|
||||
submenu_add_item(
|
||||
|
Reference in New Issue
Block a user