mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-20 00:48:11 -07:00
Add back extmainapps
This commit is contained in:
@@ -3,11 +3,14 @@
|
|||||||
#include <applications.h>
|
#include <applications.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
#include <xtreme.h>
|
||||||
|
|
||||||
#include <dialogs/dialogs.h>
|
#include <dialogs/dialogs.h>
|
||||||
#include <toolbox/path.h>
|
#include <toolbox/path.h>
|
||||||
#include <flipper_application/flipper_application.h>
|
#include <flipper_application/flipper_application.h>
|
||||||
#include <loader/firmware_api/firmware_api.h>
|
#include <loader/firmware_api/firmware_api.h>
|
||||||
|
#include <toolbox/stream/file_stream.h>
|
||||||
|
#include <core/dangerous_defines.h>
|
||||||
|
|
||||||
#define TAG "Loader"
|
#define TAG "Loader"
|
||||||
#define LOADER_MAGIC_THREAD_VALUE 0xDEADBEEF
|
#define LOADER_MAGIC_THREAD_VALUE 0xDEADBEEF
|
||||||
@@ -102,6 +105,11 @@ FuriPubSub* loader_get_pubsub(Loader* loader) {
|
|||||||
return loader->pubsub;
|
return loader->pubsub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtMainAppList_t* loader_get_ext_main_apps(Loader* loader) {
|
||||||
|
furi_assert(loader);
|
||||||
|
return &loader->ext_main_apps;
|
||||||
|
}
|
||||||
|
|
||||||
// callbacks
|
// callbacks
|
||||||
|
|
||||||
static void loader_menu_closed_callback(void* context) {
|
static void loader_menu_closed_callback(void* context) {
|
||||||
@@ -136,6 +144,28 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con
|
|||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
|
|
||||||
|
bool loader_menu_load_fap_meta(
|
||||||
|
Storage* storage,
|
||||||
|
FuriString* path,
|
||||||
|
FuriString* name,
|
||||||
|
const Icon** icon) {
|
||||||
|
*icon = NULL;
|
||||||
|
uint8_t* icon_buf = malloc(CUSTOM_ICON_MAX_SIZE);
|
||||||
|
if(!flipper_application_load_name_and_icon(path, storage, &icon_buf, name)) {
|
||||||
|
free(icon_buf);
|
||||||
|
icon_buf = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*icon = malloc(sizeof(Icon));
|
||||||
|
FURI_CONST_ASSIGN((*icon)->frame_count, 1);
|
||||||
|
FURI_CONST_ASSIGN((*icon)->frame_rate, 0);
|
||||||
|
FURI_CONST_ASSIGN((*icon)->width, 10);
|
||||||
|
FURI_CONST_ASSIGN((*icon)->height, 10);
|
||||||
|
FURI_CONST_ASSIGN_PTR((*icon)->frames, malloc(sizeof(const uint8_t*)));
|
||||||
|
FURI_CONST_ASSIGN_PTR((*icon)->frames[0], icon_buf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static Loader* loader_alloc() {
|
static Loader* loader_alloc() {
|
||||||
Loader* loader = malloc(sizeof(Loader));
|
Loader* loader = malloc(sizeof(Loader));
|
||||||
loader->pubsub = furi_pubsub_alloc();
|
loader->pubsub = furi_pubsub_alloc();
|
||||||
@@ -146,6 +176,33 @@ static Loader* loader_alloc() {
|
|||||||
loader->app.thread = NULL;
|
loader->app.thread = NULL;
|
||||||
loader->app.insomniac = false;
|
loader->app.insomniac = false;
|
||||||
loader->app.fap = NULL;
|
loader->app.fap = NULL;
|
||||||
|
ExtMainAppList_init(loader->ext_main_apps);
|
||||||
|
|
||||||
|
if(furi_hal_is_normal_boot()) {
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
FuriString* path = furi_string_alloc();
|
||||||
|
FuriString* name = furi_string_alloc();
|
||||||
|
Stream* stream = file_stream_alloc(storage);
|
||||||
|
if(file_stream_open(stream, XTREME_APPS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||||
|
while(stream_read_line(stream, path)) {
|
||||||
|
furi_string_replace_all(path, "\r", "");
|
||||||
|
furi_string_replace_all(path, "\n", "");
|
||||||
|
const Icon* icon;
|
||||||
|
if(!loader_menu_load_fap_meta(storage, path, name, &icon)) continue;
|
||||||
|
ExtMainAppList_push_back(
|
||||||
|
loader->ext_main_apps,
|
||||||
|
(ExtMainApp){
|
||||||
|
.name = strdup(furi_string_get_cstr(name)),
|
||||||
|
.path = strdup(furi_string_get_cstr(path)),
|
||||||
|
.icon = icon});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_stream_close(stream);
|
||||||
|
stream_free(stream);
|
||||||
|
furi_string_free(name);
|
||||||
|
furi_string_free(path);
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
}
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gui/icon.h>
|
||||||
|
#include <m-list.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* name;
|
||||||
|
const char* path;
|
||||||
|
const Icon* icon;
|
||||||
|
} ExtMainApp;
|
||||||
|
|
||||||
|
LIST_DEF(ExtMainAppList, ExtMainApp, M_POD_OPLIST)
|
||||||
|
|
||||||
|
ExtMainAppList_t* loader_get_ext_main_apps(Loader* loader);
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <flipper_application/flipper_application.h>
|
#include <flipper_application/flipper_application.h>
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "loader_menu.h"
|
#include "loader_menu.h"
|
||||||
|
#include "loader_extmainapp.h"
|
||||||
#include "loader_applications.h"
|
#include "loader_applications.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -19,6 +20,7 @@ struct Loader {
|
|||||||
LoaderMenu* loader_menu;
|
LoaderMenu* loader_menu;
|
||||||
LoaderApplications* loader_applications;
|
LoaderApplications* loader_applications;
|
||||||
LoaderAppData app;
|
LoaderAppData app;
|
||||||
|
ExtMainAppList_t ext_main_apps;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "loader_menu.h"
|
#include "loader_menu.h"
|
||||||
|
#include "loader_extmainapp.h"
|
||||||
|
|
||||||
#define TAG "LoaderMenu"
|
#define TAG "LoaderMenu"
|
||||||
|
|
||||||
@@ -57,8 +58,8 @@ static void loader_menu_start(const char* name) {
|
|||||||
|
|
||||||
static void loader_menu_callback(void* context, uint32_t index) {
|
static void loader_menu_callback(void* context, uint32_t index) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
const char* name = FLIPPER_APPS[index].name;
|
const char* name_or_path = (const char*)index;
|
||||||
loader_menu_start(name);
|
loader_menu_start(name_or_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loader_menu_applications_callback(void* context, uint32_t index) {
|
static void loader_menu_applications_callback(void* context, uint32_t index) {
|
||||||
@@ -103,12 +104,25 @@ static void loader_menu_build_menu(LoaderMenuApp* app, LoaderMenu* menu) {
|
|||||||
app->primary_menu,
|
app->primary_menu,
|
||||||
FLIPPER_APPS[i].name,
|
FLIPPER_APPS[i].name,
|
||||||
FLIPPER_APPS[i].icon,
|
FLIPPER_APPS[i].icon,
|
||||||
i,
|
(uint32_t)FLIPPER_APPS[i].name,
|
||||||
loader_menu_callback,
|
loader_menu_callback,
|
||||||
(void*)menu);
|
(void*)menu);
|
||||||
}
|
}
|
||||||
menu_add_item(
|
menu_add_item(
|
||||||
app->primary_menu, "Settings", &A_Settings_14, 0, loader_menu_switch_to_settings, app);
|
app->primary_menu, "Settings", &A_Settings_14, 0, loader_menu_switch_to_settings, app);
|
||||||
|
Loader* loader = furi_record_open(RECORD_LOADER);
|
||||||
|
ExtMainAppList_t* ext_main_apps = loader_get_ext_main_apps(loader);
|
||||||
|
for(size_t i = 0; i < ExtMainAppList_size(*ext_main_apps); i++) {
|
||||||
|
const ExtMainApp* ext_main_app = ExtMainAppList_get(*ext_main_apps, i);
|
||||||
|
menu_add_item(
|
||||||
|
app->primary_menu,
|
||||||
|
ext_main_app->name,
|
||||||
|
ext_main_app->icon,
|
||||||
|
(uint32_t)ext_main_app->path,
|
||||||
|
loader_menu_callback,
|
||||||
|
(void*)menu);
|
||||||
|
}
|
||||||
|
furi_record_close(RECORD_LOADER);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void loader_menu_build_submenu(LoaderMenuApp* app, LoaderMenu* loader_menu) {
|
static void loader_menu_build_submenu(LoaderMenuApp* app, LoaderMenu* loader_menu) {
|
||||||
|
|||||||
Reference in New Issue
Block a user