".fap" extention in file browser and archive tab (#1812)
* Add .fap extention, and Applications tab * Using new icon, renaming tab to Apps * Change tabs order * Add first ugly implementation of in-app icons in archive browser * Starting using FAPLoader callback * Getting all metafata from fap * add app filename fallback * using fap_loader_item_callback in archive_list_item_cb * FAP-Loader: removed minimal allocation * Removed strange code Co-authored-by: SG <who.just.the.doctor@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <core/common_defines.h>
|
||||
#include <core/log.h>
|
||||
#include "gui/modules/file_browser_worker.h"
|
||||
#include <fap_loader/fap_loader_app.h>
|
||||
#include <math.h>
|
||||
|
||||
static void
|
||||
@@ -351,16 +352,32 @@ void archive_add_app_item(ArchiveBrowserView* browser, const char* name) {
|
||||
ArchiveFile_t_clear(&item);
|
||||
}
|
||||
|
||||
static bool archive_get_fap_meta(FuriString* file_path, FuriString* fap_name, uint8_t** icon_ptr) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool success = false;
|
||||
if(fap_loader_load_name_and_icon(file_path, storage, icon_ptr, fap_name)) {
|
||||
success = true;
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return success;
|
||||
}
|
||||
|
||||
void archive_add_file_item(ArchiveBrowserView* browser, bool is_folder, const char* name) {
|
||||
furi_assert(browser);
|
||||
furi_assert(name);
|
||||
|
||||
ArchiveFile_t item;
|
||||
|
||||
ArchiveFile_t_init(&item);
|
||||
item.path = furi_string_alloc_set(name);
|
||||
archive_set_file_type(&item, furi_string_get_cstr(browser->path), is_folder, false);
|
||||
|
||||
furi_string_set(item.path, name);
|
||||
archive_set_file_type(&item, furi_string_get_cstr(browser->path), is_folder, false);
|
||||
if(item.type == ArchiveFileTypeApplication) {
|
||||
item.custom_icon_data = malloc(FAP_MANIFEST_MAX_ICON_SIZE);
|
||||
if(!archive_get_fap_meta(item.path, item.custom_name, &item.custom_icon_data)) {
|
||||
free(item.custom_icon_data);
|
||||
item.custom_icon_data = NULL;
|
||||
}
|
||||
}
|
||||
with_view_model(
|
||||
browser->view, (ArchiveBrowserViewModel * model) {
|
||||
files_array_push_back(model->files, item);
|
||||
|
@@ -16,6 +16,7 @@ static const char* tab_default_paths[] = {
|
||||
[ArchiveTabInfrared] = ANY_PATH("infrared"),
|
||||
[ArchiveTabBadUsb] = ANY_PATH("badusb"),
|
||||
[ArchiveTabU2f] = "/app:u2f",
|
||||
[ArchiveTabApplications] = ANY_PATH("apps"),
|
||||
[ArchiveTabBrowser] = STORAGE_ANY_PATH_PREFIX,
|
||||
};
|
||||
|
||||
@@ -27,6 +28,7 @@ static const char* known_ext[] = {
|
||||
[ArchiveFileTypeInfrared] = ".ir",
|
||||
[ArchiveFileTypeBadUsb] = ".txt",
|
||||
[ArchiveFileTypeU2f] = "?",
|
||||
[ArchiveFileTypeApplication] = ".fap",
|
||||
[ArchiveFileTypeUpdateManifest] = ".fuf",
|
||||
[ArchiveFileTypeFolder] = "?",
|
||||
[ArchiveFileTypeUnknown] = "*",
|
||||
@@ -41,6 +43,7 @@ static const ArchiveFileTypeEnum known_type[] = {
|
||||
[ArchiveTabInfrared] = ArchiveFileTypeInfrared,
|
||||
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
|
||||
[ArchiveTabU2f] = ArchiveFileTypeU2f,
|
||||
[ArchiveTabApplications] = ArchiveFileTypeApplication,
|
||||
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
|
||||
};
|
||||
|
||||
|
@@ -4,6 +4,8 @@
|
||||
#include <furi.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
#define FAP_MANIFEST_MAX_ICON_SIZE 32
|
||||
|
||||
typedef enum {
|
||||
ArchiveFileTypeIButton,
|
||||
ArchiveFileTypeNFC,
|
||||
@@ -13,6 +15,7 @@ typedef enum {
|
||||
ArchiveFileTypeBadUsb,
|
||||
ArchiveFileTypeU2f,
|
||||
ArchiveFileTypeUpdateManifest,
|
||||
ArchiveFileTypeApplication,
|
||||
ArchiveFileTypeFolder,
|
||||
ArchiveFileTypeUnknown,
|
||||
ArchiveFileTypeLoading,
|
||||
@@ -21,33 +24,56 @@ typedef enum {
|
||||
typedef struct {
|
||||
FuriString* path;
|
||||
ArchiveFileTypeEnum type;
|
||||
uint8_t* custom_icon_data;
|
||||
FuriString* custom_name;
|
||||
bool fav;
|
||||
bool is_app;
|
||||
} ArchiveFile_t;
|
||||
|
||||
static void ArchiveFile_t_init(ArchiveFile_t* obj) {
|
||||
obj->type = ArchiveFileTypeUnknown;
|
||||
obj->is_app = false;
|
||||
obj->fav = false;
|
||||
obj->path = furi_string_alloc();
|
||||
obj->type = ArchiveFileTypeUnknown;
|
||||
obj->custom_icon_data = NULL;
|
||||
obj->custom_name = furi_string_alloc();
|
||||
obj->fav = false;
|
||||
obj->is_app = false;
|
||||
}
|
||||
|
||||
static void ArchiveFile_t_init_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
|
||||
obj->type = src->type;
|
||||
obj->is_app = src->is_app;
|
||||
obj->fav = src->fav;
|
||||
obj->path = furi_string_alloc_set(src->path);
|
||||
obj->type = src->type;
|
||||
if(src->custom_icon_data) {
|
||||
obj->custom_icon_data = malloc(FAP_MANIFEST_MAX_ICON_SIZE);
|
||||
memcpy(obj->custom_icon_data, src->custom_icon_data, FAP_MANIFEST_MAX_ICON_SIZE);
|
||||
} else {
|
||||
obj->custom_icon_data = NULL;
|
||||
}
|
||||
obj->custom_name = furi_string_alloc_set(src->custom_name);
|
||||
obj->fav = src->fav;
|
||||
obj->is_app = src->is_app;
|
||||
}
|
||||
|
||||
static void ArchiveFile_t_set(ArchiveFile_t* obj, const ArchiveFile_t* src) {
|
||||
obj->type = src->type;
|
||||
obj->is_app = src->is_app;
|
||||
obj->fav = src->fav;
|
||||
furi_string_set(obj->path, src->path);
|
||||
obj->type = src->type;
|
||||
if(src->custom_icon_data) {
|
||||
obj->custom_icon_data = malloc(FAP_MANIFEST_MAX_ICON_SIZE);
|
||||
memcpy(obj->custom_icon_data, src->custom_icon_data, FAP_MANIFEST_MAX_ICON_SIZE);
|
||||
} else {
|
||||
obj->custom_icon_data = NULL;
|
||||
}
|
||||
furi_string_set(obj->custom_name, src->custom_name);
|
||||
obj->fav = src->fav;
|
||||
obj->is_app = src->is_app;
|
||||
}
|
||||
|
||||
static void ArchiveFile_t_clear(ArchiveFile_t* obj) {
|
||||
furi_string_free(obj->path);
|
||||
if(obj->custom_icon_data) {
|
||||
free(obj->custom_icon_data);
|
||||
obj->custom_icon_data = NULL;
|
||||
}
|
||||
furi_string_free(obj->custom_name);
|
||||
}
|
||||
|
||||
ARRAY_DEF(
|
||||
|
@@ -20,6 +20,7 @@ static const char* flipper_app_name[] = {
|
||||
[ArchiveFileTypeBadUsb] = "Bad USB",
|
||||
[ArchiveFileTypeU2f] = "U2F",
|
||||
[ArchiveFileTypeUpdateManifest] = "UpdaterApp",
|
||||
[ArchiveFileTypeApplication] = "Applications",
|
||||
};
|
||||
|
||||
static void archive_loader_callback(const void* message, void* context) {
|
||||
|
@@ -14,6 +14,7 @@ static const char* ArchiveTabNames[] = {
|
||||
[ArchiveTabInfrared] = "Infrared",
|
||||
[ArchiveTabBadUsb] = "Bad USB",
|
||||
[ArchiveTabU2f] = "U2F",
|
||||
[ArchiveTabApplications] = "Apps",
|
||||
[ArchiveTabBrowser] = "Browser",
|
||||
};
|
||||
|
||||
@@ -29,6 +30,7 @@ static const Icon* ArchiveItemIcons[] = {
|
||||
[ArchiveFileTypeFolder] = &I_dir_10px,
|
||||
[ArchiveFileTypeUnknown] = &I_unknown_10px,
|
||||
[ArchiveFileTypeLoading] = &I_loading_10px,
|
||||
[ArchiveFileTypeApplication] = &I_unknown_10px,
|
||||
};
|
||||
|
||||
void archive_browser_set_callback(
|
||||
@@ -124,12 +126,23 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
uint8_t x_offset = (model->move_fav && model->item_idx == idx) ? MOVE_OFFSET : 0;
|
||||
|
||||
ArchiveFileTypeEnum file_type = ArchiveFileTypeLoading;
|
||||
uint8_t* custom_icon_data = NULL;
|
||||
|
||||
if(archive_is_item_in_array(model, idx)) {
|
||||
ArchiveFile_t* file = files_array_get(
|
||||
model->files, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0));
|
||||
path_extract_filename(file->path, str_buf, archive_is_known_app(file->type));
|
||||
file_type = file->type;
|
||||
if(file_type == ArchiveFileTypeApplication) {
|
||||
if(file->custom_icon_data) {
|
||||
custom_icon_data = file->custom_icon_data;
|
||||
furi_string_set(str_buf, file->custom_name);
|
||||
} else {
|
||||
file_type = ArchiveFileTypeUnknown;
|
||||
path_extract_filename(file->path, str_buf, archive_is_known_app(file->type));
|
||||
}
|
||||
} else {
|
||||
path_extract_filename(file->path, str_buf, archive_is_known_app(file->type));
|
||||
}
|
||||
} else {
|
||||
furi_string_set(str_buf, "---");
|
||||
}
|
||||
@@ -143,7 +156,13 @@ static void draw_list(Canvas* canvas, ArchiveBrowserViewModel* model) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
|
||||
canvas_draw_icon(canvas, 2 + x_offset, 16 + i * FRAME_HEIGHT, ArchiveItemIcons[file_type]);
|
||||
if(custom_icon_data) {
|
||||
canvas_draw_bitmap(
|
||||
canvas, 2 + x_offset, 16 + i * FRAME_HEIGHT, 11, 10, custom_icon_data);
|
||||
} else {
|
||||
canvas_draw_icon(
|
||||
canvas, 2 + x_offset, 16 + i * FRAME_HEIGHT, ArchiveItemIcons[file_type]);
|
||||
}
|
||||
canvas_draw_str(
|
||||
canvas, 15 + x_offset, 24 + i * FRAME_HEIGHT, furi_string_get_cstr(str_buf));
|
||||
|
||||
|
@@ -26,6 +26,7 @@ typedef enum {
|
||||
ArchiveTabIButton,
|
||||
ArchiveTabBadUsb,
|
||||
ArchiveTabU2f,
|
||||
ArchiveTabApplications,
|
||||
ArchiveTabBrowser,
|
||||
ArchiveTabTotal,
|
||||
} ArchiveTabEnum;
|
||||
|
Reference in New Issue
Block a user