[FL-1300] iButton app: save selected menu item and selected file position. (#489)

* GUI module submenu: fix documentation
* GUI module submenu: add submenu_set_selected_item fn
* App iButton: use submenu_set_selected_item to store and set selected item in submenu
* App iButton: swap write and emulate in "saved key menu" scene
* App iButton: file select can now switch to the previous selected file
* App iButton: swap write and emulate indexes in "saved key menu" scene

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
SG
2021-05-25 21:04:22 +10:00
committed by GitHub
parent f49f30f8a7
commit fc5c48edef
15 changed files with 179 additions and 19 deletions

View File

@@ -387,4 +387,90 @@ bool file_select_fill_count(FileSelect* file_select) {
dir_api->close(&directory);
free(name);
return true;
}
void file_select_set_selected_file_internal(FileSelect* file_select, const char* filename) {
furi_assert(file_select);
furi_assert(filename);
furi_assert(file_select->fs_api);
furi_assert(file_select->path);
furi_assert(file_select->extension);
if(strlen(filename) == 0) return;
FileInfo file_info;
File directory;
bool result;
FS_Dir_Api* dir_api = &file_select->fs_api->dir;
const uint8_t name_length = 100;
char* name = calloc(name_length, sizeof(char));
uint16_t file_position = 0;
if(name == NULL) {
return;
}
result = dir_api->open(&directory, file_select->path);
if(!result) {
dir_api->close(&directory);
free(name);
return;
}
while(1) {
result = dir_api->read(&directory, &file_info, name, name_length);
if(directory.error_id == FSE_NOT_EXIST || name[0] == 0) {
break;
}
if(result) {
if(directory.error_id == FSE_OK) {
if(filter_file(file_select, &file_info, name)) {
if(strcmp(filename, name) == 0) {
break;
}
file_position++;
}
} else {
dir_api->close(&directory);
free(name);
return;
}
}
}
with_view_model(
file_select->view, (FileSelectModel * model) {
uint16_t max_first_file_index =
model->file_count > FILENAME_COUNT ? model->file_count - FILENAME_COUNT : 0;
model->first_file_index = file_position;
if(model->first_file_index > 0) {
model->first_file_index -= 1;
}
if(model->first_file_index >= max_first_file_index) {
model->first_file_index = max_first_file_index;
}
model->position = file_position - model->first_file_index;
return true;
});
dir_api->close(&directory);
free(name);
}
void file_select_set_selected_file(FileSelect* file_select, const char* filename) {
file_select_set_selected_file_internal(file_select, filename);
if(!file_select_fill_strings(file_select)) {
file_select->callback(false, file_select->context);
}
}

View File

@@ -20,6 +20,7 @@ void file_select_set_callback(FileSelect* file_select, FileSelectCallback callba
void file_select_set_filter(FileSelect* file_select, const char* path, const char* extension);
void file_select_set_result_buffer(FileSelect* file_select, char* buffer, uint8_t buffer_size);
bool file_select_init(FileSelect* file_select);
void file_select_set_selected_file(FileSelect* file_select, const char* filename);
#ifdef __cplusplus
}

View File

@@ -168,6 +168,42 @@ void submenu_clean(Submenu* submenu) {
});
}
void submenu_set_selected_item(Submenu* submenu, uint32_t index) {
with_view_model(
submenu->view, (SubmenuModel * model) {
uint32_t position = 0;
SubmenuItemArray_it_t it;
for(SubmenuItemArray_it(it, model->items); !SubmenuItemArray_end_p(it);
SubmenuItemArray_next(it)) {
if(index == SubmenuItemArray_cref(it)->index) {
break;
}
position++;
}
if(position >= SubmenuItemArray_size(model->items)) {
position = 0;
}
model->position = position;
model->window_position = position;
if(model->window_position > 0) {
model->window_position -= 1;
}
if(SubmenuItemArray_size(model->items) <= 4) {
model->window_position = 0;
} else {
if(model->window_position >= (SubmenuItemArray_size(model->items) - 4)) {
model->window_position = (SubmenuItemArray_size(model->items) - 4);
}
}
return true;
});
}
void submenu_process_up(Submenu* submenu) {
with_view_model(
submenu->view, (SubmenuModel * model) {

View File

@@ -10,23 +10,33 @@ typedef struct Submenu Submenu;
typedef struct SubmenuItem SubmenuItem;
typedef void (*SubmenuItemCallback)(void* context, uint32_t index);
/* Allocate and initialize submenu
/**
* @brief Allocate and initialize submenu
* This submenu is used to select one option
*/
Submenu* submenu_alloc();
/* Deinitialize and free submenu
/**
* @brief Allocate and initialize submenu for vertical display
* This submenu is used to select one option
*/
Submenu* submenu_vertical_alloc();
/**
* @brief Deinitialize and free submenu
* @param submenu - Submenu instance
*/
void submenu_free(Submenu* submenu);
/* Get submenu view
/**
* @brief Get submenu view
* @param submenu - Submenu instance
* @return View instance that can be used for embedding
*/
View* submenu_get_view(Submenu* submenu);
/* Add item to submenu
/**
* @brief Add item to submenu
* @param submenu - Submenu instance
* @param label - menu item label
* @param index - menu item index, used for callback, may be the same with other items
@@ -41,12 +51,18 @@ SubmenuItem* submenu_add_item(
SubmenuItemCallback callback,
void* callback_context);
/* Remove all items from submenu
/**
* @brief Remove all items from submenu
* @param submenu - Submenu instance
*/
void submenu_clean(Submenu* submenu);
Submenu* submenu_vertical_alloc();
/**
* @brief Set submenu item selector
* @param submenu
* @param index
*/
void submenu_set_selected_item(Submenu* submenu, uint32_t index);
#ifdef __cplusplus
}