mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-26 14:30:25 +00:00
[FL-2212] File validators and archive fixes #972
Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
84410c83b5
commit
6264ee8c3b
24 changed files with 194 additions and 52 deletions
|
@ -25,4 +25,5 @@ struct ArchiveApp {
|
|||
ArchiveBrowserView* browser;
|
||||
TextInput* text_input;
|
||||
char text_store[MAX_NAME_LEN];
|
||||
char file_extension[MAX_EXT_LEN + 1];
|
||||
};
|
||||
|
|
|
@ -272,7 +272,6 @@ void archive_enter_dir(ArchiveBrowserView* browser, string_t name) {
|
|||
with_view_model(
|
||||
browser->view, (ArchiveBrowserViewModel * model) {
|
||||
model->last_idx = model->idx;
|
||||
model->last_offset = model->list_offset;
|
||||
model->idx = 0;
|
||||
model->depth = CLAMP(model->depth + 1, MAX_DEPTH, 0);
|
||||
return false;
|
||||
|
|
|
@ -31,6 +31,40 @@ uint16_t archive_favorites_count(void* context) {
|
|||
return lines;
|
||||
}
|
||||
|
||||
static bool archive_favourites_rescan() {
|
||||
string_t buffer;
|
||||
string_init(buffer);
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
|
||||
bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
if(result) {
|
||||
while(1) {
|
||||
if(!file_worker_read_until(file_worker, buffer, '\n')) {
|
||||
break;
|
||||
}
|
||||
if(!string_size(buffer)) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool file_exists = false;
|
||||
file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists);
|
||||
if(file_exists) {
|
||||
archive_file_append(ARCHIVE_FAV_TEMP_PATH, "%s\n", string_get_cstr(buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_clear(buffer);
|
||||
|
||||
file_worker_close(file_worker);
|
||||
file_worker_remove(file_worker, ARCHIVE_FAV_PATH);
|
||||
file_worker_rename(file_worker, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH);
|
||||
|
||||
file_worker_free(file_worker);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool archive_favorites_read(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
|
@ -41,6 +75,8 @@ bool archive_favorites_read(void* context) {
|
|||
FileInfo file_info;
|
||||
string_init(buffer);
|
||||
|
||||
bool need_refresh = false;
|
||||
|
||||
bool result = file_worker_open(file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
|
||||
if(result) {
|
||||
|
@ -52,13 +88,24 @@ bool archive_favorites_read(void* context) {
|
|||
break;
|
||||
}
|
||||
|
||||
archive_add_item(browser, &file_info, string_get_cstr(buffer));
|
||||
bool file_exists = false;
|
||||
file_worker_is_file_exist(file_worker, string_get_cstr(buffer), &file_exists);
|
||||
|
||||
if(file_exists)
|
||||
archive_add_item(browser, &file_info, string_get_cstr(buffer));
|
||||
else
|
||||
need_refresh = true;
|
||||
string_reset(buffer);
|
||||
}
|
||||
}
|
||||
string_clear(buffer);
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
|
||||
if(need_refresh) {
|
||||
archive_favourites_rescan();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,14 @@ void archive_trim_file_path(char* name, bool ext) {
|
|||
}
|
||||
}
|
||||
|
||||
void archive_get_file_extension(char* name, char* ext) {
|
||||
char* dot = strrchr(name, '.');
|
||||
if(dot == NULL)
|
||||
*ext = '\0';
|
||||
else
|
||||
strncpy(ext, dot, MAX_EXT_LEN);
|
||||
}
|
||||
|
||||
void set_file_type(ArchiveFile_t* file, FileInfo* file_info) {
|
||||
furi_assert(file);
|
||||
furi_assert(file_info);
|
||||
|
|
|
@ -50,6 +50,7 @@ ARRAY_DEF(
|
|||
bool filter_by_extension(FileInfo* file_info, const char* tab_ext, const char* name);
|
||||
void set_file_type(ArchiveFile_t* file, FileInfo* file_info);
|
||||
void archive_trim_file_path(char* name, bool ext);
|
||||
void archive_get_file_extension(char* name, char* ext);
|
||||
bool archive_get_filenames(void* context, const char* path);
|
||||
bool archive_dir_empty(void* context, const char* path);
|
||||
bool archive_read_dir(void* context, const char* path);
|
||||
|
|
|
@ -18,6 +18,7 @@ void archive_scene_rename_on_enter(void* context) {
|
|||
ArchiveFile_t* current = archive_get_current_file(archive->browser);
|
||||
strlcpy(archive->text_store, string_get_cstr(current->name), MAX_NAME_LEN);
|
||||
|
||||
archive_get_file_extension(archive->text_store, archive->file_extension);
|
||||
archive_trim_file_path(archive->text_store, true);
|
||||
|
||||
text_input_set_header_text(text_input, "Rename:");
|
||||
|
@ -30,6 +31,10 @@ void archive_scene_rename_on_enter(void* context) {
|
|||
MAX_TEXT_INPUT_LEN,
|
||||
false);
|
||||
|
||||
ValidatorIsFile* validator_is_file =
|
||||
validator_is_file_alloc_init(archive_get_path(archive->browser), archive->file_extension);
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
|
||||
view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewTextInput);
|
||||
}
|
||||
|
||||
|
@ -74,6 +79,11 @@ bool archive_scene_rename_on_event(void* context, SceneManagerEvent event) {
|
|||
|
||||
void archive_scene_rename_on_exit(void* context) {
|
||||
ArchiveApp* archive = (ArchiveApp*)context;
|
||||
|
||||
// Clear view
|
||||
void* validator_context = text_input_get_validator_callback_context(archive->text_input);
|
||||
text_input_set_validator(archive->text_input, NULL, NULL);
|
||||
validator_is_file_free(validator_context);
|
||||
|
||||
text_input_reset(archive->text_input);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#define MAX_LEN_PX 110
|
||||
#define MAX_NAME_LEN 255
|
||||
#define MAX_EXT_LEN 6
|
||||
#define FRAME_HEIGHT 12
|
||||
#define MENU_ITEMS 4
|
||||
#define MAX_DEPTH 32
|
||||
|
|
|
@ -18,6 +18,9 @@ void desktop_scene_lock_menu_on_enter(void* context) {
|
|||
|
||||
desktop_lock_menu_set_callback(desktop->lock_menu, desktop_scene_lock_menu_callback, desktop);
|
||||
desktop_lock_menu_pin_set(desktop->lock_menu, desktop->settings.pincode.length > 0);
|
||||
|
||||
uint8_t idx = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu);
|
||||
desktop_lock_menu_set_idx(desktop->lock_menu, idx);
|
||||
view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewLockMenu);
|
||||
}
|
||||
|
||||
|
@ -30,6 +33,7 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
|
|||
case DesktopLockMenuEventLock:
|
||||
scene_manager_set_scene_state(
|
||||
desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedNoPin);
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
||||
consumed = true;
|
||||
break;
|
||||
|
@ -39,12 +43,14 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
|
|||
desktop->scene_manager, DesktopSceneMain, DesktopMainSceneStateLockedWithPin);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain);
|
||||
} else {
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1);
|
||||
scene_manager_next_scene(desktop->scene_manager, DesktopScenePinSetup);
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopLockMenuEventExit:
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
desktop->scene_manager, DesktopSceneMain);
|
||||
consumed = true;
|
||||
|
@ -57,6 +63,4 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) {
|
|||
}
|
||||
|
||||
void desktop_scene_lock_menu_on_exit(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
desktop_lock_menu_reset_idx(desktop->lock_menu);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "../desktop_i.h"
|
||||
#include "desktop_lock_menu.h"
|
||||
|
||||
#define LOCK_MENU_ITEMS_NB 3
|
||||
|
||||
void desktop_lock_menu_set_callback(
|
||||
DesktopLockMenuView* lock_menu,
|
||||
DesktopLockMenuViewCallback callback,
|
||||
|
@ -22,10 +24,11 @@ void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set)
|
|||
});
|
||||
}
|
||||
|
||||
void desktop_lock_menu_reset_idx(DesktopLockMenuView* lock_menu) {
|
||||
void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) {
|
||||
furi_assert(idx < LOCK_MENU_ITEMS_NB);
|
||||
with_view_model(
|
||||
lock_menu->view, (DesktopLockMenuViewModel * model) {
|
||||
model->idx = 0;
|
||||
model->idx = idx;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
@ -51,7 +54,7 @@ static void lock_menu_callback(void* context, uint8_t index) {
|
|||
}
|
||||
|
||||
void desktop_lock_menu_render(Canvas* canvas, void* model) {
|
||||
const char* Lockmenu_Items[3] = {"Lock", "Lock with PIN", "DUMB mode"};
|
||||
const char* Lockmenu_Items[LOCK_MENU_ITEMS_NB] = {"Lock", "Lock with PIN", "DUMB mode"};
|
||||
|
||||
DesktopLockMenuViewModel* m = model;
|
||||
canvas_clear(canvas);
|
||||
|
@ -60,14 +63,15 @@ void desktop_lock_menu_render(Canvas* canvas, void* model) {
|
|||
canvas_draw_icon(canvas, 116, 0 + STATUS_BAR_Y_SHIFT, &I_DoorRight_70x55);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
for(uint8_t i = 0; i < 3; ++i) {
|
||||
for(uint8_t i = 0; i < LOCK_MENU_ITEMS_NB; ++i) {
|
||||
const char* str = Lockmenu_Items[i];
|
||||
|
||||
if(i == 1 && !m->pin_set) str = "Set PIN";
|
||||
if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not implemented";
|
||||
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str);
|
||||
if(str != NULL)
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str);
|
||||
|
||||
if(m->idx == i) elements_frame(canvas, 15, 1 + (i * 17) + STATUS_BAR_Y_SHIFT, 98, 15);
|
||||
}
|
||||
|
@ -90,9 +94,9 @@ bool desktop_lock_menu_input(InputEvent* event, void* context) {
|
|||
lock_menu->view, (DesktopLockMenuViewModel * model) {
|
||||
model->hint_timeout = 0; // clear hint timeout
|
||||
if(event->key == InputKeyUp) {
|
||||
model->idx = CLAMP(model->idx - 1, 2, 0);
|
||||
model->idx = CLAMP(model->idx - 1, LOCK_MENU_ITEMS_NB - 1, 0);
|
||||
} else if(event->key == InputKeyDown) {
|
||||
model->idx = CLAMP(model->idx + 1, 2, 0);
|
||||
model->idx = CLAMP(model->idx + 1, LOCK_MENU_ITEMS_NB - 1, 0);
|
||||
}
|
||||
idx = model->idx;
|
||||
return true;
|
||||
|
|
|
@ -28,6 +28,6 @@ void desktop_lock_menu_set_callback(
|
|||
|
||||
View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu);
|
||||
void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set);
|
||||
void desktop_lock_menu_reset_idx(DesktopLockMenuView* lock_menu);
|
||||
void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx);
|
||||
DesktopLockMenuView* desktop_lock_menu_alloc();
|
||||
void desktop_lock_menu_free(DesktopLockMenuView* lock_menu);
|
||||
|
|
|
@ -64,6 +64,10 @@ public:
|
|||
SceneAddValue,
|
||||
};
|
||||
|
||||
static const char* app_folder;
|
||||
static const char* app_extension;
|
||||
static const char* app_filetype;
|
||||
|
||||
iButtonAppViewManager* get_view_manager();
|
||||
void switch_to_next_scene(Scene index);
|
||||
void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list);
|
||||
|
@ -137,10 +141,6 @@ private:
|
|||
static const uint8_t text_store_size = 128;
|
||||
char text_store[text_store_size + 1];
|
||||
|
||||
static const char* app_folder;
|
||||
static const char* app_extension;
|
||||
static const char* app_filetype;
|
||||
|
||||
bool load_key_data(string_t key_path);
|
||||
void make_app_folder();
|
||||
};
|
|
@ -25,6 +25,10 @@ void iButtonSceneSaveName::on_enter(iButtonApp* app) {
|
|||
text_input_set_result_callback(
|
||||
text_input, callback, app, app->get_text_store(), IBUTTON_KEY_NAME_SIZE, key_name_empty);
|
||||
|
||||
ValidatorIsFile* validator_is_file =
|
||||
validator_is_file_alloc_init(app->app_folder, app->app_extension);
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
|
||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewTextInput);
|
||||
}
|
||||
|
||||
|
@ -48,6 +52,11 @@ bool iButtonSceneSaveName::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||
|
||||
void iButtonSceneSaveName::on_exit(iButtonApp* app) {
|
||||
TextInput* text_input = app->get_view_manager()->get_text_input();
|
||||
|
||||
void* validator_context = text_input_get_validator_callback_context(text_input);
|
||||
text_input_set_validator(text_input, NULL, NULL);
|
||||
validator_is_file_free((ValidatorIsFile*)validator_context);
|
||||
|
||||
text_input_reset(text_input);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@ void IrdaAppSceneEditRename::on_enter(IrdaApp* app) {
|
|||
strncpy(app->get_text_store(0), remote_name.c_str(), app->get_text_store_size());
|
||||
enter_name_length = IrdaAppRemoteManager::max_remote_name_length;
|
||||
text_input_set_header_text(text_input, "Name the remote");
|
||||
|
||||
ValidatorIsFile* validator_is_file =
|
||||
validator_is_file_alloc_init(app->irda_directory, app->irda_extension);
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
}
|
||||
|
||||
text_input_set_result_callback(
|
||||
|
@ -59,4 +63,10 @@ bool IrdaAppSceneEditRename::on_event(IrdaApp* app, IrdaAppEvent* event) {
|
|||
}
|
||||
|
||||
void IrdaAppSceneEditRename::on_exit(IrdaApp* app) {
|
||||
TextInput* text_input = app->get_view_manager()->get_text_input();
|
||||
|
||||
void* validator_context = text_input_get_validator_callback_context(text_input);
|
||||
text_input_set_validator(text_input, NULL, NULL);
|
||||
|
||||
if(validator_context != NULL) validator_is_file_free((ValidatorIsFile*)validator_context);
|
||||
}
|
||||
|
|
|
@ -35,9 +35,9 @@ void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool need_restore) {
|
|||
|
||||
string_printf(string_header, "Delete %s?", key.get_name());
|
||||
line_1->set_text(
|
||||
string_get_cstr(string_header), 64, 19, AlignCenter, AlignBottom, FontPrimary);
|
||||
string_get_cstr(string_header), 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
|
||||
line_2->set_text(
|
||||
string_get_cstr(string_data), 64, 29, AlignCenter, AlignBottom, FontSecondary);
|
||||
string_get_cstr(string_data), 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
switch(key.get_type()) {
|
||||
case LfrfidKeyType::KeyEM4100:
|
||||
|
@ -52,12 +52,13 @@ void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool need_restore) {
|
|||
break;
|
||||
}
|
||||
line_3->set_text(
|
||||
string_get_cstr(string_decrypted), 64, 39, AlignCenter, AlignBottom, FontSecondary);
|
||||
string_get_cstr(string_decrypted), 64, 39, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
line_4->set_text(
|
||||
lfrfid_key_get_type_string(key.get_type()),
|
||||
64,
|
||||
49,
|
||||
0,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
FontSecondary);
|
||||
|
|
|
@ -36,9 +36,9 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) {
|
|||
|
||||
switch(app->worker.key.get_type()) {
|
||||
case LfrfidKeyType::KeyEM4100:
|
||||
line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary);
|
||||
line_2_text->set_text("Mod:", 65, 35, AlignRight, AlignBottom, FontSecondary);
|
||||
line_3_text->set_text("ID:", 65, 47, AlignRight, AlignBottom, FontSecondary);
|
||||
line_1_text->set_text("HEX:", 65, 23, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_2_text->set_text("Mod:", 65, 35, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_3_text->set_text("ID:", 65, 47, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
|
||||
for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) {
|
||||
string_cat_printf(string[0], "%02X", data[i]);
|
||||
|
@ -48,17 +48,17 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) {
|
|||
string_printf(string[2], "%03u,%05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
|
||||
|
||||
line_1_value->set_text(
|
||||
string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary);
|
||||
string_get_cstr(string[0]), 68, 23, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_2_value->set_text(
|
||||
string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary);
|
||||
string_get_cstr(string[1]), 68, 35, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_3_value->set_text(
|
||||
string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary);
|
||||
string_get_cstr(string[2]), 68, 47, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
break;
|
||||
case LfrfidKeyType::KeyH10301:
|
||||
case LfrfidKeyType::KeyI40134:
|
||||
line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary);
|
||||
line_2_text->set_text("FC:", 65, 35, AlignRight, AlignBottom, FontSecondary);
|
||||
line_3_text->set_text("Card:", 65, 47, AlignRight, AlignBottom, FontSecondary);
|
||||
line_1_text->set_text("HEX:", 65, 23, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_2_text->set_text("FC:", 65, 35, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_3_text->set_text("Card:", 65, 47, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
|
||||
for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) {
|
||||
string_cat_printf(string[0], "%02X", data[i]);
|
||||
|
@ -68,11 +68,11 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) {
|
|||
string_printf(string[2], "%u", (uint16_t)((data[1] << 8) | (data[2])));
|
||||
|
||||
line_1_value->set_text(
|
||||
string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary);
|
||||
string_get_cstr(string[0]), 68, 23, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_2_value->set_text(
|
||||
string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary);
|
||||
string_get_cstr(string[1]), 68, 35, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_3_value->set_text(
|
||||
string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary);
|
||||
string_get_cstr(string[2]), 68, 47, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
9
applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp
Executable file → Normal file
9
applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp
Executable file → Normal file
|
@ -21,6 +21,10 @@ void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool need_restore) {
|
|||
app->worker.key.get_name_length(),
|
||||
key_name_empty);
|
||||
|
||||
ValidatorIsFile* validator_is_file =
|
||||
validator_is_file_alloc_init(app->app_folder, app->app_extension);
|
||||
text_input->set_validator(validator_is_file_callback, validator_is_file);
|
||||
|
||||
app->view_controller.switch_to<TextInputVM>();
|
||||
}
|
||||
|
||||
|
@ -46,6 +50,11 @@ bool LfRfidAppSceneSaveName::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
|||
}
|
||||
|
||||
void LfRfidAppSceneSaveName::on_exit(LfRfidApp* app) {
|
||||
void* validator_context =
|
||||
app->view_controller.get<TextInputVM>()->get_validator_callback_context();
|
||||
app->view_controller.get<TextInputVM>()->set_validator(NULL, NULL);
|
||||
validator_is_file_free((ValidatorIsFile*)validator_context);
|
||||
|
||||
app->view_controller.get<TextInputVM>()->clean();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,9 @@ void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool need_restore) {
|
|||
string_cat_printf(string_data, "%02X", data[i]);
|
||||
}
|
||||
|
||||
line_1->set_text(key.get_name(), 64, 17, AlignCenter, AlignBottom, FontSecondary);
|
||||
line_2->set_text(string_get_cstr(string_data), 64, 29, AlignCenter, AlignBottom, FontPrimary);
|
||||
line_1->set_text(key.get_name(), 64, 17, 128 - 2, AlignCenter, AlignBottom, FontSecondary);
|
||||
line_2->set_text(
|
||||
string_get_cstr(string_data), 64, 29, 0, AlignCenter, AlignBottom, FontPrimary);
|
||||
|
||||
switch(key.get_type()) {
|
||||
case LfrfidKeyType::KeyEM4100:
|
||||
|
@ -44,12 +45,13 @@ void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool need_restore) {
|
|||
break;
|
||||
}
|
||||
line_3->set_text(
|
||||
string_get_cstr(string_decrypted), 64, 39, AlignCenter, AlignBottom, FontSecondary);
|
||||
string_get_cstr(string_decrypted), 64, 39, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
line_4->set_text(
|
||||
lfrfid_key_get_type_string(key.get_type()),
|
||||
64,
|
||||
49,
|
||||
0,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
FontSecondary);
|
||||
|
|
|
@ -9,8 +9,17 @@ StringElement::~StringElement() {
|
|||
|
||||
void StringElement::draw(Canvas* canvas) {
|
||||
if(text) {
|
||||
string_t line;
|
||||
string_init(line);
|
||||
string_set_str(line, text);
|
||||
|
||||
canvas_set_font(canvas, font);
|
||||
elements_multiline_text_aligned(canvas, x, y, horizontal, vertical, text);
|
||||
if(fit_width != 0) {
|
||||
elements_string_fit_width(canvas, line, fit_width);
|
||||
}
|
||||
elements_multiline_text_aligned(canvas, x, y, horizontal, vertical, string_get_cstr(line));
|
||||
|
||||
string_clear(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +31,7 @@ void StringElement::set_text(
|
|||
const char* _text,
|
||||
uint8_t _x,
|
||||
uint8_t _y,
|
||||
uint8_t _fit_w,
|
||||
Align _horizontal,
|
||||
Align _vertical,
|
||||
Font _font) {
|
||||
|
@ -29,8 +39,9 @@ void StringElement::set_text(
|
|||
text = _text;
|
||||
x = _x;
|
||||
y = _y;
|
||||
fit_width = _fit_w;
|
||||
horizontal = _horizontal;
|
||||
vertical = _vertical;
|
||||
font = _font;
|
||||
unlock_model(true);
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ public:
|
|||
const char* text = NULL,
|
||||
uint8_t x = 0,
|
||||
uint8_t y = 0,
|
||||
uint8_t fit_width = 0,
|
||||
Align horizontal = AlignLeft,
|
||||
Align vertical = AlignTop,
|
||||
Font font = FontPrimary);
|
||||
|
@ -20,6 +21,7 @@ private:
|
|||
const char* text = NULL;
|
||||
uint8_t x = 0;
|
||||
uint8_t y = 0;
|
||||
uint8_t fit_width = 0;
|
||||
Align horizontal = AlignLeft;
|
||||
Align vertical = AlignTop;
|
||||
Font font = FontPrimary;
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
#include <lib/toolbox/path.h>
|
||||
#include <lib/flipper_file/flipper_file.h>
|
||||
|
||||
static const char* nfc_app_folder = "/any/nfc";
|
||||
static const char* nfc_app_extension = ".nfc";
|
||||
static const char* nfc_app_shadow_extension = ".shd";
|
||||
static const char* nfc_file_header = "Flipper NFC device";
|
||||
static const uint32_t nfc_file_version = 2;
|
||||
|
||||
|
@ -243,7 +240,7 @@ static bool nfc_device_save_file(
|
|||
|
||||
do {
|
||||
// Create nfc directory if necessary
|
||||
if(!storage_simply_mkdir(dev->storage, nfc_app_folder)) break;
|
||||
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
|
||||
|
@ -281,12 +278,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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static bool nfc_device_load_data(NfcDevice* dev, string_t path) {
|
||||
|
@ -300,9 +297,9 @@ 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);
|
||||
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);
|
||||
string_cat_printf(temp_str, "%s", NFC_APP_SHADOW_EXTENSION);
|
||||
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
|
||||
|
@ -374,15 +371,15 @@ bool nfc_file_select(NfcDevice* dev) {
|
|||
// Input events and views are managed by file_select
|
||||
bool res = dialog_file_select_show(
|
||||
dev->dialogs,
|
||||
nfc_app_folder,
|
||||
nfc_app_extension,
|
||||
NFC_APP_FOLDER,
|
||||
NFC_APP_EXTENSION,
|
||||
dev->file_name,
|
||||
sizeof(dev->file_name),
|
||||
dev->dev_name);
|
||||
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);
|
||||
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);
|
||||
if(res) {
|
||||
nfc_device_set_name(dev, dev->file_name);
|
||||
|
@ -409,12 +406,12 @@ 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);
|
||||
string_init_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);
|
||||
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;
|
||||
|
@ -437,10 +434,10 @@ bool nfc_device_restore(NfcDevice* dev) {
|
|||
|
||||
do {
|
||||
string_init_printf(
|
||||
path, "%s/%s%s", nfc_app_folder, dev->dev_name, nfc_app_shadow_extension);
|
||||
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);
|
||||
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);
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#define NFC_DEV_NAME_MAX_LEN 22
|
||||
#define NFC_FILE_NAME_MAX_LEN 120
|
||||
|
||||
#define NFC_APP_FOLDER "/any/nfc"
|
||||
#define NFC_APP_EXTENSION ".nfc"
|
||||
#define NFC_APP_SHADOW_EXTENSION ".shd"
|
||||
|
||||
typedef enum {
|
||||
NfcDeviceNfca,
|
||||
NfcDeviceNfcb,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "../nfc_i.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <gui/modules/validators.h>
|
||||
|
||||
#define SCENE_SAVE_NAME_CUSTOM_EVENT (0UL)
|
||||
|
||||
|
@ -29,6 +30,11 @@ void nfc_scene_save_name_on_enter(void* context) {
|
|||
nfc->text_store,
|
||||
NFC_DEV_NAME_MAX_LEN,
|
||||
dev_name_empty);
|
||||
|
||||
ValidatorIsFile* validator_is_file =
|
||||
validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION);
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput);
|
||||
}
|
||||
|
||||
|
@ -60,5 +66,9 @@ void nfc_scene_save_name_on_exit(void* context) {
|
|||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
// Clear view
|
||||
void* validator_context = text_input_get_validator_callback_context(nfc->text_input);
|
||||
text_input_set_validator(nfc->text_input, NULL, NULL);
|
||||
validator_is_file_free(validator_context);
|
||||
|
||||
text_input_reset(nfc->text_input);
|
||||
}
|
||||
|
|
|
@ -29,3 +29,11 @@ void TextInputVM::set_result_callback(
|
|||
void TextInputVM::set_header_text(const char* text) {
|
||||
text_input_set_header_text(text_input, text);
|
||||
}
|
||||
|
||||
void TextInputVM::set_validator(TextInputValidatorCallback callback, void* callback_context) {
|
||||
text_input_set_validator(text_input, callback, callback_context);
|
||||
}
|
||||
|
||||
void* TextInputVM::get_validator_callback_context() {
|
||||
return text_input_get_validator_callback_context(text_input);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ public:
|
|||
*/
|
||||
void set_header_text(const char* text);
|
||||
|
||||
void set_validator(TextInputValidatorCallback callback, void* callback_context);
|
||||
|
||||
void* get_validator_callback_context();
|
||||
|
||||
private:
|
||||
TextInput* text_input;
|
||||
};
|
Loading…
Reference in a new issue