feat(reynabot): Show dedicated speaker selection screen on launch
This commit is contained in:
@@ -50,6 +50,10 @@ typedef struct {
|
|||||||
lv_obj_t* btn_grace;
|
lv_obj_t* btn_grace;
|
||||||
lv_obj_t* btn_elias;
|
lv_obj_t* btn_elias;
|
||||||
|
|
||||||
|
bool speaker_selected;
|
||||||
|
lv_obj_t* speaker_select_cont;
|
||||||
|
lv_obj_t* app_main_cont;
|
||||||
|
|
||||||
// PTT control
|
// PTT control
|
||||||
bool is_pressed;
|
bool is_pressed;
|
||||||
bool start_session;
|
bool start_session;
|
||||||
@@ -281,30 +285,21 @@ static void speaker_event_cb(lv_event_t* e) {
|
|||||||
lv_obj_t* target = lv_event_get_target(e);
|
lv_obj_t* target = lv_event_get_target(e);
|
||||||
lv_event_code_t code = lv_event_get_code(e);
|
lv_event_code_t code = lv_event_get_code(e);
|
||||||
|
|
||||||
if (code == LV_EVENT_CLICKED) {
|
if (code == LV_EVENT_CLICKED && !ctx->speaker_selected) {
|
||||||
if (target == ctx->btn_grace) {
|
if (target == ctx->btn_grace) {
|
||||||
strcpy(ctx->device_id, "grace-esp32");
|
strcpy(ctx->device_id, "grace-esp32");
|
||||||
// Grace active styling
|
|
||||||
lv_obj_set_style_bg_color(ctx->btn_grace, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_border_color(ctx->btn_grace, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_text_color(ctx->btn_grace, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
|
|
||||||
|
|
||||||
// Elias inactive styling
|
|
||||||
lv_obj_set_style_bg_color(ctx->btn_elias, lv_color_hex(0x1C1B22), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_border_color(ctx->btn_elias, lv_color_hex(0x2D2B36), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_text_color(ctx->btn_elias, lv_color_hex(0x9E9E9E), LV_PART_MAIN);
|
|
||||||
} else if (target == ctx->btn_elias) {
|
} else if (target == ctx->btn_elias) {
|
||||||
strcpy(ctx->device_id, "elias-esp32");
|
strcpy(ctx->device_id, "elias-esp32");
|
||||||
// Elias active styling
|
|
||||||
lv_obj_set_style_bg_color(ctx->btn_elias, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_border_color(ctx->btn_elias, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_text_color(ctx->btn_elias, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
|
|
||||||
|
|
||||||
// Grace inactive styling
|
|
||||||
lv_obj_set_style_bg_color(ctx->btn_grace, lv_color_hex(0x1C1B22), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_border_color(ctx->btn_grace, lv_color_hex(0x2D2B36), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_text_color(ctx->btn_grace, lv_color_hex(0x9E9E9E), LV_PART_MAIN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->speaker_selected = true;
|
||||||
|
|
||||||
|
// Hide selection screen, show main screen
|
||||||
|
lv_obj_add_flag(ctx->speaker_select_cont, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_remove_flag(ctx->app_main_cont, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
// Trigger UI update to refresh status and PTT button
|
||||||
|
ctx->ui_update_pending = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +310,7 @@ static void ptt_event_cb(lv_event_t* e) {
|
|||||||
|
|
||||||
if (code == LV_EVENT_PRESSED) {
|
if (code == LV_EVENT_PRESSED) {
|
||||||
ctx->is_pressed = true;
|
ctx->is_pressed = true;
|
||||||
if (ctx->state == STATE_IDLE || ctx->state == STATE_ERROR) {
|
if (ctx->state == STATE_IDLE || ctx->state == ERROR_NONE) {
|
||||||
ctx->start_session = true;
|
ctx->start_session = true;
|
||||||
}
|
}
|
||||||
} else if (code == LV_EVENT_RELEASED || code == LV_EVENT_PRESS_LOST) {
|
} else if (code == LV_EVENT_RELEASED || code == LV_EVENT_PRESS_LOST) {
|
||||||
@@ -338,6 +333,13 @@ static void update_ui(ReynaBotCtx* ctx) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ctx->speaker_selected) {
|
||||||
|
lv_label_set_text(ctx->lbl_status, "Choose Speaker");
|
||||||
|
lv_obj_set_style_text_color(ctx->lbl_status, lv_color_hex(0x9E9E9E), LV_PART_MAIN);
|
||||||
|
tt_lvgl_unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ctx->state) {
|
switch (ctx->state) {
|
||||||
case STATE_IDLE:
|
case STATE_IDLE:
|
||||||
lv_label_set_text(ctx->lbl_status, "Ready");
|
lv_label_set_text(ctx->lbl_status, "Ready");
|
||||||
@@ -633,60 +635,94 @@ static void on_show(AppHandle app, void* data, lv_obj_t* parent) {
|
|||||||
lv_obj_align(ctx->lbl_status, LV_ALIGN_RIGHT_MID, -10, 0);
|
lv_obj_align(ctx->lbl_status, LV_ALIGN_RIGHT_MID, -10, 0);
|
||||||
lv_obj_set_style_text_color(ctx->lbl_status, lv_color_hex(0x9E9E9E), LV_PART_MAIN);
|
lv_obj_set_style_text_color(ctx->lbl_status, lv_color_hex(0x9E9E9E), LV_PART_MAIN);
|
||||||
|
|
||||||
|
// Initial state
|
||||||
|
ctx->speaker_selected = false;
|
||||||
|
|
||||||
// Default to Grace if device_id is not already configured to elias-esp32
|
// Default to Grace if device_id is not already configured to elias-esp32
|
||||||
if (strcmp(ctx->device_id, "elias-esp32") != 0) {
|
if (strcmp(ctx->device_id, "elias-esp32") != 0) {
|
||||||
strcpy(ctx->device_id, "grace-esp32");
|
strcpy(ctx->device_id, "grace-esp32");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Speaker Selection Container (Grace / Elias)
|
// 1. Speaker Selection Container (Startup Screen)
|
||||||
lv_obj_t* speaker_row = lv_obj_create(parent);
|
ctx->speaker_select_cont = lv_obj_create(parent);
|
||||||
lv_obj_set_size(speaker_row, lv_pct(95), 45);
|
lv_obj_set_width(ctx->speaker_select_cont, lv_pct(95));
|
||||||
|
lv_obj_set_flex_grow(ctx->speaker_select_cont, 1);
|
||||||
|
lv_obj_set_flex_flow(ctx->speaker_select_cont, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_flex_align(ctx->speaker_select_cont, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
|
lv_obj_set_style_pad_all(ctx->speaker_select_cont, 0, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_bg_opa(ctx->speaker_select_cont, 0, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_border_width(ctx->speaker_select_cont, 0, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_pad_row(ctx->speaker_select_cont, 16, LV_PART_MAIN);
|
||||||
|
|
||||||
|
// Title Prompt
|
||||||
|
lv_obj_t* prompt_lbl = lv_label_create(ctx->speaker_select_cont);
|
||||||
|
lv_label_set_text(prompt_lbl, "Who is speaking?");
|
||||||
|
lv_obj_set_style_text_color(prompt_lbl, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
|
||||||
|
|
||||||
|
// Row of two selection buttons
|
||||||
|
lv_obj_t* speaker_row = lv_obj_create(ctx->speaker_select_cont);
|
||||||
|
lv_obj_set_size(speaker_row, lv_pct(100), 140);
|
||||||
lv_obj_set_flex_flow(speaker_row, LV_FLEX_FLOW_ROW);
|
lv_obj_set_flex_flow(speaker_row, LV_FLEX_FLOW_ROW);
|
||||||
lv_obj_set_flex_align(speaker_row, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
lv_obj_set_flex_align(speaker_row, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
lv_obj_set_style_pad_all(speaker_row, 0, LV_PART_MAIN);
|
lv_obj_set_style_pad_all(speaker_row, 0, LV_PART_MAIN);
|
||||||
lv_obj_set_style_bg_opa(speaker_row, 0, LV_PART_MAIN);
|
lv_obj_set_style_bg_opa(speaker_row, 0, LV_PART_MAIN);
|
||||||
lv_obj_set_style_border_width(speaker_row, 0, LV_PART_MAIN);
|
lv_obj_set_style_border_width(speaker_row, 0, LV_PART_MAIN);
|
||||||
|
|
||||||
|
// Grace Button (Girl)
|
||||||
ctx->btn_grace = lv_btn_create(speaker_row);
|
ctx->btn_grace = lv_btn_create(speaker_row);
|
||||||
lv_obj_set_size(ctx->btn_grace, lv_pct(47), 35);
|
lv_obj_set_size(ctx->btn_grace, lv_pct(46), 130);
|
||||||
lv_obj_set_style_radius(ctx->btn_grace, 8, LV_PART_MAIN);
|
lv_obj_set_flex_flow(ctx->btn_grace, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_flex_align(ctx->btn_grace, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
|
lv_obj_set_style_pad_all(ctx->btn_grace, 8, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_pad_row(ctx->btn_grace, 8, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_radius(ctx->btn_grace, 12, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_bg_color(ctx->btn_grace, lv_color_hex(0x1C1B22), LV_PART_MAIN);
|
||||||
lv_obj_set_style_border_width(ctx->btn_grace, 1, LV_PART_MAIN);
|
lv_obj_set_style_border_width(ctx->btn_grace, 1, LV_PART_MAIN);
|
||||||
lv_obj_t* lbl_grace = lv_label_create(ctx->btn_grace);
|
lv_obj_set_style_border_color(ctx->btn_grace, lv_color_hex(0x2D2B36), LV_PART_MAIN);
|
||||||
lv_label_set_text(lbl_grace, "Grace");
|
|
||||||
lv_obj_center(lbl_grace);
|
|
||||||
lv_obj_add_event_cb(ctx->btn_grace, speaker_event_cb, LV_EVENT_CLICKED, ctx);
|
lv_obj_add_event_cb(ctx->btn_grace, speaker_event_cb, LV_EVENT_CLICKED, ctx);
|
||||||
|
|
||||||
|
lv_obj_t* icon_grace = lv_label_create(ctx->btn_grace);
|
||||||
|
lv_label_set_text(icon_grace, "🚺");
|
||||||
|
|
||||||
|
lv_obj_t* lbl_grace = lv_label_create(ctx->btn_grace);
|
||||||
|
lv_label_set_text(lbl_grace, "Grace");
|
||||||
|
lv_obj_set_style_text_color(lbl_grace, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
|
||||||
|
|
||||||
|
// Elias Button (Boy)
|
||||||
ctx->btn_elias = lv_btn_create(speaker_row);
|
ctx->btn_elias = lv_btn_create(speaker_row);
|
||||||
lv_obj_set_size(ctx->btn_elias, lv_pct(47), 35);
|
lv_obj_set_size(ctx->btn_elias, lv_pct(46), 130);
|
||||||
lv_obj_set_style_radius(ctx->btn_elias, 8, LV_PART_MAIN);
|
lv_obj_set_flex_flow(ctx->btn_elias, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_flex_align(ctx->btn_elias, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
|
lv_obj_set_style_pad_all(ctx->btn_elias, 8, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_pad_row(ctx->btn_elias, 8, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_radius(ctx->btn_elias, 12, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_bg_color(ctx->btn_elias, lv_color_hex(0x1C1B22), LV_PART_MAIN);
|
||||||
lv_obj_set_style_border_width(ctx->btn_elias, 1, LV_PART_MAIN);
|
lv_obj_set_style_border_width(ctx->btn_elias, 1, LV_PART_MAIN);
|
||||||
lv_obj_t* lbl_elias = lv_label_create(ctx->btn_elias);
|
lv_obj_set_style_border_color(ctx->btn_elias, lv_color_hex(0x2D2B36), LV_PART_MAIN);
|
||||||
lv_label_set_text(lbl_elias, "Elias");
|
|
||||||
lv_obj_center(lbl_elias);
|
|
||||||
lv_obj_add_event_cb(ctx->btn_elias, speaker_event_cb, LV_EVENT_CLICKED, ctx);
|
lv_obj_add_event_cb(ctx->btn_elias, speaker_event_cb, LV_EVENT_CLICKED, ctx);
|
||||||
|
|
||||||
// Set initial highlights and text colors
|
lv_obj_t* icon_elias = lv_label_create(ctx->btn_elias);
|
||||||
if (strcmp(ctx->device_id, "elias-esp32") == 0) {
|
lv_label_set_text(icon_elias, "🚹");
|
||||||
lv_obj_set_style_bg_color(ctx->btn_elias, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_border_color(ctx->btn_elias, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_text_color(ctx->btn_elias, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
|
|
||||||
|
|
||||||
lv_obj_set_style_bg_color(ctx->btn_grace, lv_color_hex(0x1C1B22), LV_PART_MAIN);
|
lv_obj_t* lbl_elias = lv_label_create(ctx->btn_elias);
|
||||||
lv_obj_set_style_border_color(ctx->btn_grace, lv_color_hex(0x2D2B36), LV_PART_MAIN);
|
lv_label_set_text(lbl_elias, "Elias");
|
||||||
lv_obj_set_style_text_color(ctx->btn_grace, lv_color_hex(0x9E9E9E), LV_PART_MAIN);
|
lv_obj_set_style_text_color(lbl_elias, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
|
||||||
} else {
|
|
||||||
lv_obj_set_style_bg_color(ctx->btn_grace, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_border_color(ctx->btn_grace, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
|
||||||
lv_obj_set_style_text_color(ctx->btn_grace, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
|
|
||||||
|
|
||||||
lv_obj_set_style_bg_color(ctx->btn_elias, lv_color_hex(0x1C1B22), LV_PART_MAIN);
|
// 2. Main App Container (Usual App Screen)
|
||||||
lv_obj_set_style_border_color(ctx->btn_elias, lv_color_hex(0x2D2B36), LV_PART_MAIN);
|
ctx->app_main_cont = lv_obj_create(parent);
|
||||||
lv_obj_set_style_text_color(ctx->btn_elias, lv_color_hex(0x9E9E9E), LV_PART_MAIN);
|
lv_obj_set_width(ctx->app_main_cont, lv_pct(95));
|
||||||
}
|
lv_obj_set_flex_grow(ctx->app_main_cont, 1);
|
||||||
|
lv_obj_set_flex_flow(ctx->app_main_cont, LV_FLEX_FLOW_COLUMN);
|
||||||
|
lv_obj_set_flex_align(ctx->app_main_cont, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||||
|
lv_obj_set_style_pad_all(ctx->app_main_cont, 0, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_pad_row(ctx->app_main_cont, 12, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_bg_opa(ctx->app_main_cont, 0, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_border_width(ctx->app_main_cont, 0, LV_PART_MAIN);
|
||||||
|
lv_obj_add_flag(ctx->app_main_cont, LV_OBJ_FLAG_HIDDEN); // Hidden by default
|
||||||
|
|
||||||
// Conversation bubble container
|
// Conversation bubble container
|
||||||
lv_obj_t* conv_card = lv_obj_create(parent);
|
lv_obj_t* conv_card = lv_obj_create(ctx->app_main_cont);
|
||||||
lv_obj_set_width(conv_card, lv_pct(95));
|
lv_obj_set_width(conv_card, lv_pct(100));
|
||||||
lv_obj_set_flex_grow(conv_card, 1);
|
lv_obj_set_flex_grow(conv_card, 1);
|
||||||
lv_obj_set_flex_flow(conv_card, LV_FLEX_FLOW_COLUMN);
|
lv_obj_set_flex_flow(conv_card, LV_FLEX_FLOW_COLUMN);
|
||||||
lv_obj_set_flex_align(conv_card, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
|
lv_obj_set_flex_align(conv_card, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
|
||||||
@@ -728,7 +764,7 @@ static void on_show(AppHandle app, void* data, lv_obj_t* parent) {
|
|||||||
lv_obj_set_style_text_color(ctx->lbl_response, lv_color_hex(0xE0E0E0), LV_PART_MAIN);
|
lv_obj_set_style_text_color(ctx->lbl_response, lv_color_hex(0xE0E0E0), LV_PART_MAIN);
|
||||||
|
|
||||||
// Push-to-Talk Button
|
// Push-to-Talk Button
|
||||||
ctx->btn_ptt = lv_btn_create(parent);
|
ctx->btn_ptt = lv_btn_create(ctx->app_main_cont);
|
||||||
lv_obj_set_size(ctx->btn_ptt, 180, 50);
|
lv_obj_set_size(ctx->btn_ptt, 180, 50);
|
||||||
lv_obj_set_style_radius(ctx->btn_ptt, 25, LV_PART_MAIN);
|
lv_obj_set_style_radius(ctx->btn_ptt, 25, LV_PART_MAIN);
|
||||||
lv_obj_set_style_bg_color(ctx->btn_ptt, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
lv_obj_set_style_bg_color(ctx->btn_ptt, lv_color_hex(0x6200EE), LV_PART_MAIN);
|
||||||
|
|||||||
Reference in New Issue
Block a user