implemented basic desktop

This commit is contained in:
Ken Van Hoeylandt 2024-01-03 14:13:13 +01:00
parent f6c547ad45
commit 48d2fd6c2d
19 changed files with 241 additions and 219 deletions

View File

@ -12,11 +12,16 @@ typedef struct _lv_obj_t lv_obj_t;
typedef enum {
AppTypeService,
AppTypeSystem,
AppTypeDesktop,
AppTypeUser
} AppType;
typedef enum {
AppStackSizeNormal = 2048
AppStackSizeTiny = 512,
AppStackSizeSmall = 1024,
AppStackSizeNormal = 2048,
AppStackSizeLarge = 4096,
AppStackSizeHuge = 8192,
} AppStackSize;
typedef void (*AppOnStart)(void _Nonnull* parameter);

View File

@ -64,16 +64,16 @@ const AppManifest _Nullable* app_manifest_registry_find_by_id(const char* id) {
return (manifest != NULL) ? *manifest : NULL;
}
void app_manifest_registry_for_each_of_type(AppType type, AppManifestCallback callback) {
void app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback) {
APP_REGISTRY_FOR_EACH(manifest, {
if (manifest->type == type) {
callback(manifest);
callback(manifest, context);
}
});
}
void app_manifest_registry_for_each(AppManifestCallback callback) {
void app_manifest_registry_for_each(AppManifestCallback callback, void* _Nullable context) {
APP_REGISTRY_FOR_EACH(manifest, {
callback(manifest);
callback(manifest, context);
});
}

View File

@ -9,14 +9,14 @@ extern "C" {
extern const AppManifest* const INTERNAL_APP_MANIFESTS[];
extern const size_t INTERNAL_APP_COUNT;
typedef void (*AppManifestCallback)(const AppManifest*);
typedef void (*AppManifestCallback)(const AppManifest*, void* context);
void app_manifest_registry_init();
void app_manifest_registry_add(const AppManifest _Nonnull* manifest);
void app_manifest_registry_remove(const AppManifest _Nonnull* manifest);
const AppManifest _Nullable* app_manifest_registry_find_by_id(const char* id);
void app_manifest_registry_for_each(AppManifestCallback callback);
void app_manifest_registry_for_each_of_type(AppType type, AppManifestCallback callback);
void app_manifest_registry_for_each(AppManifestCallback callback, void* _Nullable context);
void app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback);
#ifdef __cplusplus
}

View File

Before

Width:  |  Height:  |  Size: 274 B

After

Width:  |  Height:  |  Size: 274 B

View File

Before

Width:  |  Height:  |  Size: 224 B

After

Width:  |  Height:  |  Size: 224 B

View File

@ -1,18 +1,59 @@
#include "desktop.h"
#include "furi_extra_defines.h"
#include "lvgl.h"
#include "check.h"
#include "record.h"
#include "apps/services/loader/loader.h"
#include "apps/services/gui/gui.h"
#include "apps/services/gui/view_port.h"
#include "app_manifest_registry.h"
static void desktop_start(void* param) {
UNUSED(param);
printf("desktop app init\n");
static void on_open_app(lv_event_t* e) {
lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_CLICKED) {
const AppManifest* manifest = lv_event_get_user_data(e);
FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, {
loader_start_app_nonblocking(loader, manifest->id, NULL);
})
}
}
static void add_app_to_list(const AppManifest* manifest, void* _Nullable parent) {
furi_check(parent);
lv_obj_t* list = (lv_obj_t*)parent;
lv_obj_t* btn = lv_list_add_btn(list, LV_SYMBOL_FILE, manifest->name);
lv_obj_add_event_cb(btn, &on_open_app, LV_EVENT_CLICKED, (void*)manifest);
}
static void desktop_show(lv_obj_t* parent, void* context) {
lv_obj_t* list = lv_list_create(parent);
lv_obj_set_size(list, LV_PCT(100), LV_PCT(100));
lv_obj_center(list);
lv_list_add_text(list, "System");
app_manifest_registry_for_each_of_type(AppTypeSystem, list, add_app_to_list);
lv_list_add_text(list, "User");
app_manifest_registry_for_each_of_type(AppTypeUser, list, add_app_to_list);
}
static void desktop_start() {
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, &desktop_show, NULL);
FURI_RECORD_TRANSACTION(RECORD_GUI, Gui*, gui, {
gui_add_view_port(gui, view_port, GuiLayerDesktop);
})
}
static void desktop_stop() {
furi_crash("desktop_stop is not implemented");
}
const AppManifest desktop_app = {
.id = "desktop",
.name = "Desktop",
.icon = NULL,
.type = AppTypeService,
.type = AppTypeDesktop,
.on_start = &desktop_start,
.on_stop = NULL,
.on_stop = &desktop_stop,
.on_show = NULL,
.stack_size = AppStackSizeNormal
};

View File

@ -1,176 +1,69 @@
#include "check.h"
#include "gui_i.h"
#include "log.h"
#include "record.h"
#include "esp_lvgl_port.h"
#include "apps/services/gui/widgets/widgets.h"
#include "apps/services/loader/loader.h"
static void gui_redraw_status_bar(Gui* gui, bool need_attention) {
/*
ViewPortArray_it_t it;
uint8_t left_used = 0;
uint8_t right_used = 0;
uint8_t width;
#define TAG "gui"
canvas_frame_set(
gui->lvgl_parent, GUI_STATUS_BAR_X, GUI_STATUS_BAR_Y, GUI_DISPLAY_WIDTH, GUI_STATUS_BAR_HEIGHT);
static lv_obj_t* screen_with_top_bar(lv_obj_t* parent) {
lv_obj_set_style_bg_blacken(parent);
// for support black theme - paint white area and
// draw icon with transparent white color
lv_obj_t* vertical_container = lv_obj_create(parent);
lv_obj_set_size(vertical_container, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(vertical_container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_no_padding(vertical_container);
lv_obj_set_style_bg_blacken(vertical_container);
canvas_set_color(gui->canvas, ColorWhite);
canvas_draw_box(gui->canvas, 1, 1, 9, 7);
canvas_draw_box(gui->canvas, 7, 3, 58, 6);
canvas_draw_box(gui->canvas, 61, 1, 32, 7);
canvas_draw_box(gui->canvas, 89, 3, 38, 6);
canvas_set_color(gui->canvas, ColorBlack);
canvas_set_bitmap_mode(gui->canvas, 1);
canvas_draw_icon(gui->canvas, 0, 0, &I_Background_128x11);
canvas_set_bitmap_mode(gui->canvas, 0);
top_bar(vertical_container);
// Right side
uint8_t x = GUI_DISPLAY_WIDTH - 1;
ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]);
while(!ViewPortArray_end_p(it) && right_used < GUI_STATUS_BAR_WIDTH) {
ViewPort* view_port = *ViewPortArray_ref(it);
if(view_port_is_enabled(view_port)) {
width = view_port_get_width(view_port);
if(!width) width = 8;
// Recalculate next position
right_used += (width + 2);
x -= (width + 2);
// Prepare work area background
canvas_frame_set(
gui->canvas,
x - 1,
GUI_STATUS_BAR_Y + 1,
width + 2,
GUI_STATUS_BAR_WORKAREA_HEIGHT + 2);
canvas_set_color(gui->canvas, ColorWhite);
canvas_draw_box(
gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas));
canvas_set_color(gui->canvas, ColorBlack);
// ViewPort draw
canvas_frame_set(
gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT);
view_port_draw(view_port, gui->canvas);
lv_obj_t* child_container = lv_obj_create(vertical_container);
lv_obj_set_width(child_container, LV_PCT(100));
lv_obj_set_flex_grow(child_container, 1);
lv_obj_set_style_no_padding(vertical_container);
lv_obj_set_style_bg_blacken(vertical_container);
return child_container;
}
static lv_obj_t* screen_with_top_bar_and_toolbar(lv_obj_t* parent) {
lv_obj_set_style_bg_blacken(parent);
lv_obj_t* vertical_container = lv_obj_create(parent);
lv_obj_set_size(vertical_container, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(vertical_container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_no_padding(vertical_container);
lv_obj_set_style_bg_blacken(vertical_container);
top_bar(vertical_container);
FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, {
const AppManifest* manifest = loader_get_current_app(loader);
if (manifest != NULL) {
toolbar(vertical_container, TOP_BAR_HEIGHT, manifest);
}
ViewPortArray_next(it);
}
// Draw frame around icons on the right
if(right_used) {
canvas_frame_set(
gui->canvas,
GUI_DISPLAY_WIDTH - 3 - right_used,
GUI_STATUS_BAR_Y,
right_used + 3,
GUI_STATUS_BAR_HEIGHT);
canvas_set_color(gui->canvas, ColorBlack);
canvas_draw_rframe(
gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1);
canvas_draw_line(
gui->canvas,
canvas_width(gui->canvas) - 2,
1,
canvas_width(gui->canvas) - 2,
canvas_height(gui->canvas) - 2);
canvas_draw_line(
gui->canvas,
1,
canvas_height(gui->canvas) - 2,
canvas_width(gui->canvas) - 2,
canvas_height(gui->canvas) - 2);
}
})
// Left side
x = 2;
ViewPortArray_it(it, gui->layers[GuiLayerStatusBarLeft]);
while(!ViewPortArray_end_p(it) && (right_used + left_used) < GUI_STATUS_BAR_WIDTH) {
ViewPort* view_port = *ViewPortArray_ref(it);
if(view_port_is_enabled(view_port)) {
width = view_port_get_width(view_port);
if(!width) width = 8;
// Prepare work area background
canvas_frame_set(
gui->canvas,
x - 1,
GUI_STATUS_BAR_Y + 1,
width + 2,
GUI_STATUS_BAR_WORKAREA_HEIGHT + 2);
canvas_set_color(gui->canvas, ColorWhite);
canvas_draw_box(
gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas));
canvas_set_color(gui->canvas, ColorBlack);
// ViewPort draw
canvas_frame_set(
gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT);
view_port_draw(view_port, gui->canvas);
// Recalculate next position
left_used += (width + 2);
x += (width + 2);
}
ViewPortArray_next(it);
}
// Extra notification
if(need_attention) {
width = icon_get_width(&I_Hidden_window_9x8);
// Prepare work area background
canvas_frame_set(
gui->canvas,
x - 1,
GUI_STATUS_BAR_Y + 1,
width + 2,
GUI_STATUS_BAR_WORKAREA_HEIGHT + 2);
canvas_set_color(gui->canvas, ColorWhite);
canvas_draw_box(gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas));
canvas_set_color(gui->canvas, ColorBlack);
// Draw Icon
canvas_frame_set(
gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_WORKAREA_HEIGHT);
canvas_draw_icon(gui->canvas, 0, 0, &I_Hidden_window_9x8);
// Recalculate next position
left_used += (width + 2);
x += (width + 2);
}
// Draw frame around icons on the left
if(left_used) {
canvas_frame_set(gui->canvas, 0, 0, left_used + 3, GUI_STATUS_BAR_HEIGHT);
canvas_draw_rframe(
gui->canvas, 0, 0, canvas_width(gui->canvas), canvas_height(gui->canvas), 1);
canvas_draw_line(
gui->canvas,
canvas_width(gui->canvas) - 2,
1,
canvas_width(gui->canvas) - 2,
canvas_height(gui->canvas) - 2);
canvas_draw_line(
gui->canvas,
1,
canvas_height(gui->canvas) - 2,
canvas_width(gui->canvas) - 2,
canvas_height(gui->canvas) - 2);
}
*/
lv_obj_t* spacer = lv_obj_create(vertical_container);
lv_obj_set_size(spacer, 2, 2);
lv_obj_set_style_bg_blacken(spacer);
lv_obj_t* child_container = lv_obj_create(vertical_container);
lv_obj_set_width(child_container, LV_PCT(100));
lv_obj_set_flex_grow(child_container, 1);
lv_obj_set_style_no_padding(vertical_container);
lv_obj_set_style_bg_blacken(vertical_container);
return child_container;
}
static bool gui_redraw_window(Gui* gui) {
ViewPort* view_port = gui_view_port_find_enabled(gui->layers[GuiLayerWindow]);
if (view_port) {
lv_obj_set_style_bg_blacken(gui->lvgl_parent);
lv_obj_t* vertical_container = lv_obj_create(gui->lvgl_parent);
lv_obj_set_size(vertical_container, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(vertical_container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_no_padding(vertical_container);
lv_obj_set_style_bg_blacken(vertical_container);
top_bar(vertical_container);
lv_obj_t* window_parent = lv_obj_create(vertical_container);
lv_obj_set_width(window_parent, LV_PCT(100));
lv_obj_set_flex_grow(window_parent, 1);
lv_obj_set_style_no_padding(vertical_container);
lv_obj_set_style_bg_blacken(vertical_container);
view_port_draw(view_port, window_parent);
lv_obj_t* container = screen_with_top_bar_and_toolbar(gui->lvgl_parent);
view_port_draw(view_port, container);
return true;
} else {
return false;
@ -178,14 +71,14 @@ static bool gui_redraw_window(Gui* gui) {
}
static bool gui_redraw_desktop(Gui* gui) {
/*
canvas_frame_set(gui->lvgl_parent, 0, 0, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT);
ViewPort* view_port = gui_view_port_find_enabled(gui->layers[GuiLayerDesktop]);
if(view_port) {
view_port_draw(view_port, gui->lvgl_parent);
if (view_port) {
lv_obj_t* container = screen_with_top_bar(gui->lvgl_parent);
view_port_draw(view_port, container);
return true;
} else {
FURI_LOG_E(TAG, "no desktop layer found");
}
*/
return false;
}
@ -207,12 +100,10 @@ void gui_redraw(Gui* gui) {
furi_check(lvgl_port_lock(100));
lv_obj_clean(gui->lvgl_parent);
gui_redraw_desktop(gui);
if (!gui_redraw_fs(gui)) {
if (!gui_redraw_window(gui)) {
gui_redraw_desktop(gui);
}
gui_redraw_status_bar(gui, false);
}
lvgl_port_unlock();

View File

@ -1,8 +1,9 @@
#include "apps/services/gui/widgets/widgets.h"
#include "check.h"
#include "esp_lvgl_port.h"
#include "gui.h"
#include "gui_i.h"
#include "view_port_i.h"
#include "esp_lvgl_port.h"
#define TAG "viewport"
@ -90,6 +91,7 @@ void view_port_draw(ViewPort* view_port, lv_obj_t* parent) {
if (view_port->draw_callback) {
lv_obj_clean(parent);
lv_obj_set_style_no_padding(parent);
view_port->draw_callback(parent, view_port->draw_callback_context);
}

View File

@ -0,0 +1,40 @@
#include "toolbar.h"
#include "record.h"
#include "apps/services/gui/widgets/widgets.h"
#include "apps/services/loader/loader.h"
static void app_toolbar_close(lv_event_t* event) {
FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, {
loader_stop_app(loader);
})
}
void toolbar(lv_obj_t* parent, lv_coord_t offset_y, const AppManifest* manifest) {
lv_obj_t* toolbar = lv_obj_create(parent);
lv_obj_set_width(toolbar, LV_PCT(100));
lv_obj_set_height(toolbar, TOOLBAR_HEIGHT);
lv_obj_set_pos(toolbar, 0, offset_y);
lv_obj_set_style_no_padding(toolbar);
lv_obj_center(toolbar);
lv_obj_set_flex_flow(toolbar, LV_FLEX_FLOW_ROW);
lv_obj_t* close_button = lv_btn_create(toolbar);
lv_obj_set_size(close_button, TOOLBAR_HEIGHT - 4, TOOLBAR_HEIGHT - 4);
lv_obj_set_style_no_padding(close_button);
lv_obj_add_event_cb(close_button, &app_toolbar_close,LV_EVENT_CLICKED, NULL);
lv_obj_t* close_button_image = lv_img_create(close_button);
lv_img_set_src(close_button_image, LV_SYMBOL_CLOSE);
lv_obj_align(close_button_image, LV_ALIGN_CENTER, 0, 0);
lv_obj_t* label_container = lv_obj_create(toolbar);
lv_obj_set_style_no_padding(label_container);
lv_obj_set_height(label_container, LV_PCT(100));
lv_obj_set_flex_grow(label_container, 1);
lv_obj_t* label = lv_label_create(label_container);
lv_label_set_text(label, manifest->name);
lv_obj_set_style_text_font(label, &lv_font_montserrat_18, 0);
lv_obj_set_size(label, LV_PCT(100), TOOLBAR_FONT_HEIGHT);
lv_obj_set_pos(label, 0, (TOOLBAR_HEIGHT - TOOLBAR_FONT_HEIGHT - 10) / 2);
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "lvgl.h"
#include "app_manifest.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TOOLBAR_HEIGHT 40
#define TOOLBAR_FONT_HEIGHT 18
void toolbar(lv_obj_t* parent, lv_coord_t offset_y, const AppManifest* manifest);
#ifdef __cplusplus
}
#endif

View File

@ -22,5 +22,5 @@ void top_bar(lv_obj_t* parent) {
lv_obj_set_style_bg_blacken(wifi);
lv_obj_set_style_img_recolor(wifi, lv_color_white(), 0);
lv_obj_set_style_img_recolor_opa(wifi, 255, 0);
lv_img_set_src(wifi, "A:/assets/wifi-off.png");
lv_img_set_src(wifi, "A:/assets/ic_small_wifi_off.png");
}

View File

@ -2,7 +2,15 @@
#include "lvgl.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TOP_BAR_ICON_SIZE 18
#define TOP_BAR_HEIGHT (TOP_BAR_ICON_SIZE + 2)
void top_bar(lv_obj_t* parent);
#ifdef __cplusplus
}
#endif

View File

@ -1,6 +1,15 @@
#pragma once
#include "top_bar.h"
#include "toolbar.h"
#ifdef __cplusplus
extern "C" {
#endif
void lv_obj_set_style_bg_blacken(lv_obj_t* obj);
void lv_obj_set_style_no_padding(lv_obj_t* obj);
#ifdef __cplusplus
}
#endif

View File

@ -51,6 +51,15 @@ void loader_stop_app(Loader* loader) {
furi_message_queue_put(loader->queue, &message, FuriWaitForever);
}
const AppManifest* _Nullable loader_get_current_app(Loader* loader) {
App* app = loader->app_data.app;
if (app != NULL) {
return app->manifest;
} else {
return NULL;
}
}
FuriPubSub* loader_get_pubsub(Loader* loader) {
furi_assert(loader);
// it's safe to return pubsub without locking
@ -123,6 +132,10 @@ static void loader_start_app_with_manifest(
const AppManifest* _Nonnull manifest,
const char* args
) {
if (manifest->type != AppTypeUser && manifest->type != AppTypeSystem) {
furi_crash("app type not supported by loader");
}
App* _Nonnull app = furi_app_alloc(manifest);
loader->app_data.app = app;
loader->app_data.args = (void*)args;
@ -136,18 +149,9 @@ static void loader_start_app_with_manifest(
loader->app_data.view_port = view_port;
view_port_draw_callback_set(view_port, manifest->on_show, NULL);
switch (manifest->type) {
case AppTypeService:
furi_crash("service apps cannot have an on_show implementation");
case AppTypeSystem:
case AppTypeUser:
FURI_RECORD_TRANSACTION(RECORD_GUI, Gui*, gui, {
gui_add_view_port(gui, view_port, GuiLayerWindow);
})
break;
default:
furi_crash("viewport not implemented for app type");
}
FURI_RECORD_TRANSACTION(RECORD_GUI, Gui*, gui, {
gui_add_view_port(gui, view_port, GuiLayerWindow);
})
} else {
loader->app_data.view_port = NULL;
}

View File

@ -2,6 +2,7 @@
#include "furi_core.h"
#include "furi_string.h"
#include "pubsub.h"
#include "app_manifest.h"
#ifdef __cplusplus
extern "C" {
@ -47,6 +48,7 @@ void loader_start_app_nonblocking(Loader* loader, const char* id, const char* ar
void loader_stop_app(Loader* loader);
const AppManifest* _Nullable loader_get_current_app(Loader* loader);
/**
* @brief Start application with GUI error message
* @param[in] instance loader instance

View File

@ -8,23 +8,27 @@
#define TAG "nanobake"
// System services
extern const AppManifest desktop_app;
extern const AppManifest gui_app;
extern const AppManifest loader_app;
// Desktop
extern const AppManifest desktop_app;
// System apps
extern const AppManifest system_info_app;
void start_service(const AppManifest* _Nonnull manifest) {
// TODO: keep track of running services
void start_service(const AppManifest* _Nonnull manifest, void* _Nullable context) {
UNUSED(context);
FURI_LOG_I(TAG, "Starting service %s", manifest->name);
furi_check(manifest->on_start, "service must define on_start");
manifest->on_start(NULL);
// TODO: keep track of running services
}
static void register_apps(Config* _Nonnull config) {
FURI_LOG_I(TAG, "Registering core apps");
app_manifest_registry_add(&desktop_app);
app_manifest_registry_add(&gui_app);
app_manifest_registry_add(&desktop_app);
app_manifest_registry_add(&loader_app);
app_manifest_registry_add(&system_info_app);
@ -36,7 +40,13 @@ static void register_apps(Config* _Nonnull config) {
static void start_services() {
FURI_LOG_I(TAG, "Starting services");
app_manifest_registry_for_each_of_type(AppTypeService, start_service);
app_manifest_registry_for_each_of_type(AppTypeService, NULL, start_service);
FURI_LOG_I(TAG, "Startup complete");
}
static void start_desktop() {
FURI_LOG_I(TAG, "Starting desktop");
desktop_app.on_start(NULL);
FURI_LOG_I(TAG, "Startup complete");
}
@ -51,4 +61,5 @@ __attribute__((unused)) extern void nanobake_start(Config* _Nonnull config) {
register_apps(config);
start_services();
start_desktop();
}

View File

@ -3,14 +3,6 @@
#include "apps/services/gui/gui.h"
#include "apps/services/loader/loader.h"
static void on_button_click(lv_event_t _Nonnull* event) {
UNUSED(event);
FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, {
loader_start_app_nonblocking(loader, "systeminfo", NULL);
})
}
static void app_show(lv_obj_t* parent, void* context) {
UNUSED(context);
@ -19,13 +11,7 @@ static void app_show(lv_obj_t* parent, void* context) {
lv_obj_set_width(label, 200);
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
lv_label_set_text(label, "Hello, world!");
lv_obj_align(label, LV_ALIGN_CENTER, 0, -30);
lv_obj_t* btn = lv_btn_create(parent);
label = lv_label_create(btn);
lv_label_set_text_static(label, "System Info");
lv_obj_align(btn, LV_ALIGN_CENTER, 0, 30);
lv_obj_add_event_cb(btn, on_button_click, LV_EVENT_CLICKED, NULL);
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
}
const AppManifest hello_world_app = {

View File

@ -20,11 +20,11 @@ __attribute__((unused)) void app_main(void) {
nanobake_start(&config);
FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, {
FuriString* error_message = furi_string_alloc();
if (loader_start_app(loader, hello_world_app.id, NULL, error_message) != LoaderStatusOk) {
FURI_LOG_E(hello_world_app.id, "%s\r\n", furi_string_get_cstr(error_message));
}
furi_string_free(error_message);
});
// FURI_RECORD_TRANSACTION(RECORD_LOADER, Loader*, loader, {
// FuriString* error_message = furi_string_alloc();
// if (loader_start_app(loader, hello_world_app.id, NULL, error_message) != LoaderStatusOk) {
// FURI_LOG_E(hello_world_app.id, "%s\r\n", furi_string_get_cstr(error_message));
// }
// furi_string_free(error_message);
// });
}

View File

@ -1,7 +1,13 @@
CONFIG_IDF_TARGET="esp32"
CONFIG_LV_COLOR_16_SWAP=y
CONFIG_LV_USE_USER_DATA=y
CONFIG_LV_USE_FS_STDIO=y
CONFIG_LV_FS_STDIO_LETTER=65
CONFIG_LV_FS_STDIO_PATH=""
CONFIG_LV_FS_STDIO_CACHE_SIZE=4096
CONFIG_LV_USE_PNG=y
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"