[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,4 +1,7 @@
#include "lfrfid_app.h"
#include "assets_icons.h"
#include "furi/common_defines.h"
#include "m-string.h"
#include "scene/lfrfid_app_scene_start.h"
#include "scene/lfrfid_app_scene_read.h"
#include "scene/lfrfid_app_scene_read_success.h"
@@ -31,9 +34,11 @@ LfRfidApp::LfRfidApp()
, storage{"storage"}
, dialogs{"dialogs"}
, text_store(40) {
string_init_set_str(file_path, app_folder);
}
LfRfidApp::~LfRfidApp() {
string_clear(file_path);
}
void LfRfidApp::run(void* _args) {
@@ -42,7 +47,8 @@ void LfRfidApp::run(void* _args) {
make_app_folder();
if(strlen(args)) {
load_key_data(args, &worker.key);
string_set_str(file_path, args);
load_key_data(file_path, &worker.key);
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
scene_controller.process(100, SceneType::Emulate);
} else {
@@ -69,65 +75,49 @@ void LfRfidApp::run(void* _args) {
}
bool LfRfidApp::save_key(RfidKey* key) {
string_t file_name;
bool result = false;
make_app_folder();
string_init_printf(file_name, "%s/%s%s", app_folder, key->get_name(), app_extension);
result = save_key_data(string_get_cstr(file_name), key);
string_clear(file_name);
if(string_end_with_str_p(file_path, app_extension)) {
size_t filename_start = string_search_rchar(file_path, '/');
string_left(file_path, filename_start);
}
string_cat_printf(file_path, "/%s%s", key->get_name(), app_extension);
result = save_key_data(file_path, key);
return result;
}
bool LfRfidApp::load_key_from_file_select(bool need_restore) {
TextStore* filename_ts = new TextStore(64);
bool result = false;
if(need_restore) {
result = dialog_file_select_show(
dialogs,
app_folder,
app_extension,
filename_ts->text,
filename_ts->text_size,
worker.key.get_name());
} else {
result = dialog_file_select_show(
dialogs, app_folder, app_extension, filename_ts->text, filename_ts->text_size, NULL);
if(!need_restore) {
string_set_str(file_path, app_folder);
}
bool result = dialog_file_browser_show(
dialogs, file_path, file_path, app_extension, true, &I_125_10px, true);
if(result) {
string_t key_str;
string_init_printf(key_str, "%s/%s%s", app_folder, filename_ts->text, app_extension);
result = load_key_data(string_get_cstr(key_str), &worker.key);
string_clear(key_str);
result = load_key_data(file_path, &worker.key);
}
delete filename_ts;
return result;
}
bool LfRfidApp::delete_key(RfidKey* key) {
string_t file_name;
bool result = false;
string_init_printf(file_name, "%s/%s%s", app_folder, key->get_name(), app_extension);
result = storage_simply_remove(storage, string_get_cstr(file_name));
string_clear(file_name);
return result;
UNUSED(key);
return storage_simply_remove(storage, string_get_cstr(file_path));
}
bool LfRfidApp::load_key_data(const char* path, RfidKey* key) {
bool LfRfidApp::load_key_data(string_t path, RfidKey* key) {
FlipperFormat* file = flipper_format_file_alloc(storage);
bool result = false;
string_t str_result;
string_init(str_result);
do {
if(!flipper_format_file_open_existing(file, path)) break;
if(!flipper_format_file_open_existing(file, string_get_cstr(path))) break;
// header
uint32_t version;
@@ -149,7 +139,7 @@ bool LfRfidApp::load_key_data(const char* path, RfidKey* key) {
break;
loaded_key.set_data(key_data, loaded_key.get_type_data_count());
path_extract_filename_no_ext(path, str_result);
path_extract_filename(path, str_result, true);
loaded_key.set_name(string_get_cstr(str_result));
*key = loaded_key;
@@ -166,12 +156,12 @@ bool LfRfidApp::load_key_data(const char* path, RfidKey* key) {
return result;
}
bool LfRfidApp::save_key_data(const char* path, RfidKey* key) {
bool LfRfidApp::save_key_data(string_t path, RfidKey* key) {
FlipperFormat* file = flipper_format_file_alloc(storage);
bool result = false;
do {
if(!flipper_format_file_open_always(file, path)) break;
if(!flipper_format_file_open_always(file, string_get_cstr(path))) break;
if(!flipper_format_write_header_cstr(file, app_filetype, 1)) break;
if(!flipper_format_write_comment_cstr(file, "Key type can be EM4100, H10301 or I40134"))
break;

View File

@@ -1,4 +1,5 @@
#pragma once
#include "m-string.h"
#include <furi.h>
#include <furi_hal.h>
@@ -76,6 +77,8 @@ public:
TextStore text_store;
string_t file_path;
void run(void* args);
static const char* app_folder;
@@ -86,8 +89,8 @@ public:
bool load_key_from_file_select(bool need_restore);
bool delete_key(RfidKey* key);
bool load_key_data(const char* path, RfidKey* key);
bool save_key_data(const char* path, RfidKey* key);
bool load_key_data(string_t path, RfidKey* key);
bool save_key_data(string_t path, RfidKey* key);
void make_app_folder();
};

View File

@@ -1,11 +1,14 @@
#include "lfrfid_app_scene_save_name.h"
#include "m-string.h"
#include <lib/toolbox/random_name.h>
#include <lib/toolbox/path.h>
void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) {
const char* key_name = app->worker.key.get_name();
bool key_name_empty = !strcmp(key_name, "");
if(key_name_empty) {
string_set_str(app->file_path, app->app_folder);
set_random_name(app->text_store.text, app->text_store.text_size);
} else {
app->text_store.set("%s", key_name);
@@ -21,10 +24,17 @@ void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) {
app->worker.key.get_name_length(),
key_name_empty);
string_t folder_path;
string_init(folder_path);
path_extract_dirname(string_get_cstr(app->file_path), folder_path);
ValidatorIsFile* validator_is_file =
validator_is_file_alloc_init(app->app_folder, app->app_extension, key_name);
validator_is_file_alloc_init(string_get_cstr(folder_path), app->app_extension, key_name);
text_input->set_validator(validator_is_file_callback, validator_is_file);
string_clear(folder_path);
app->view_controller.switch_to<TextInputVM>();
}