Files
Momentum-Firmware/applications/system/js_app/modules/js_gui/dialog.c
porta 8a95cb8d6b [FL-3893] JS modules (#3841)
* feat: backport js_gpio from unleashed
* feat: backport js_keyboard, TextInputModel::minimum_length from unleashed
* fix: api version inconsistency
* style: js_gpio
* build: fix submodule ._ .
* refactor: js_gpio
* docs: type declarations for gpio
* feat: gpio interrupts
* fix: js_gpio freeing, resetting and minor stylistic changes
* style: js_gpio
* style: mlib array, fixme's
* feat: js_gpio adc
* feat: js_event_loop
* docs: js_event_loop
* feat: js_event_loop subscription cancellation
* feat: js_event_loop + js_gpio integration
* fix: js_event_loop memory leak
* feat: stop event loop on back button
* test: js: basic, math, event_loop
* feat: js_event_loop queue
* feat: js linkage to previously loaded plugins
* build: fix ci errors
* feat: js module ordered teardown
* feat: js_gui_defer_free
* feat: basic hourglass view
* style: JS ASS (Argument Schema for Scripts)
* fix: js_event_loop mem leaks and lifetime problems
* fix: crashing test and pvs false positives
* feat: mjs custom obj destructors, gui submenu view
* refactor: yank js_gui_defer_free (yuck)
* refactor: maybe_unsubscribe
* empty_screen, docs, typing fix-ups
* docs: navigation event & demo
* feat: submenu setHeader
* feat: text_input
* feat: text_box
* docs: text_box availability
* ci: silence irrelevant pvs low priority warning
* style: use furistring
* style: _get_at -> _safe_get
* fix: built-in module name assignment
* feat: js_dialog; refactor, optimize: js_gui
* docs: js_gui
* ci: silence pvs warning: Memory allocation is infallible
* style: fix storage spelling
* feat: foreign pointer signature checks
* feat: js_storage
* docs: js_storage
* fix: my unit test was breaking other tests ;_;
* ci: fix ci?
* Make doxygen happy
* docs: flipper, math, notification, global
* style: review suggestions
* style: review fixups
* fix: badusb demo script
* docs: badusb
* ci: add nofl
* ci: make linter happy
* Bump api version

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
2024-10-14 19:42:11 +01:00

130 lines
4.3 KiB
C

#include "../../js_modules.h" // IWYU pragma: keep
#include "js_gui.h"
#include "../js_event_loop/js_event_loop.h"
#include <gui/modules/dialog_ex.h>
#define QUEUE_LEN 2
typedef struct {
FuriMessageQueue* queue;
JsEventLoopContract contract;
} JsDialogCtx;
static mjs_val_t
input_transformer(struct mjs* mjs, FuriMessageQueue* queue, JsDialogCtx* context) {
UNUSED(context);
DialogExResult result;
furi_check(furi_message_queue_get(queue, &result, 0) == FuriStatusOk);
const char* string;
if(result == DialogExResultLeft) {
string = "left";
} else if(result == DialogExResultCenter) {
string = "center";
} else if(result == DialogExResultRight) {
string = "right";
} else {
furi_crash();
}
return mjs_mk_string(mjs, string, ~0, false);
}
static void input_callback(DialogExResult result, JsDialogCtx* context) {
furi_check(furi_message_queue_put(context->queue, &result, 0) == FuriStatusOk);
}
static bool
header_assign(struct mjs* mjs, DialogEx* dialog, JsViewPropValue value, JsDialogCtx* context) {
UNUSED(mjs);
UNUSED(context);
dialog_ex_set_header(dialog, value.string, 64, 0, AlignCenter, AlignTop);
return true;
}
static bool
text_assign(struct mjs* mjs, DialogEx* dialog, JsViewPropValue value, JsDialogCtx* context) {
UNUSED(mjs);
UNUSED(context);
dialog_ex_set_text(dialog, value.string, 64, 32, AlignCenter, AlignCenter);
return true;
}
static bool
left_assign(struct mjs* mjs, DialogEx* dialog, JsViewPropValue value, JsDialogCtx* context) {
UNUSED(mjs);
UNUSED(context);
dialog_ex_set_left_button_text(dialog, value.string);
return true;
}
static bool
center_assign(struct mjs* mjs, DialogEx* dialog, JsViewPropValue value, JsDialogCtx* context) {
UNUSED(mjs);
UNUSED(context);
dialog_ex_set_center_button_text(dialog, value.string);
return true;
}
static bool
right_assign(struct mjs* mjs, DialogEx* dialog, JsViewPropValue value, JsDialogCtx* context) {
UNUSED(mjs);
UNUSED(context);
dialog_ex_set_right_button_text(dialog, value.string);
return true;
}
static JsDialogCtx* ctx_make(struct mjs* mjs, DialogEx* dialog, mjs_val_t view_obj) {
JsDialogCtx* context = malloc(sizeof(JsDialogCtx));
context->queue = furi_message_queue_alloc(QUEUE_LEN, sizeof(DialogExResult));
context->contract = (JsEventLoopContract){
.magic = JsForeignMagic_JsEventLoopContract,
.object_type = JsEventLoopObjectTypeQueue,
.object = context->queue,
.non_timer =
{
.event = FuriEventLoopEventIn,
.transformer = (JsEventLoopTransformer)input_transformer,
},
};
mjs_set(mjs, view_obj, "input", ~0, mjs_mk_foreign(mjs, &context->contract));
dialog_ex_set_result_callback(dialog, (DialogExResultCallback)input_callback);
dialog_ex_set_context(dialog, context);
return context;
}
static void ctx_destroy(DialogEx* input, JsDialogCtx* context, FuriEventLoop* loop) {
UNUSED(input);
furi_event_loop_maybe_unsubscribe(loop, context->queue);
furi_message_queue_free(context->queue);
free(context);
}
static const JsViewDescriptor view_descriptor = {
.alloc = (JsViewAlloc)dialog_ex_alloc,
.free = (JsViewFree)dialog_ex_free,
.get_view = (JsViewGetView)dialog_ex_get_view,
.custom_make = (JsViewCustomMake)ctx_make,
.custom_destroy = (JsViewCustomDestroy)ctx_destroy,
.prop_cnt = 5,
.props = {
(JsViewPropDescriptor){
.name = "header",
.type = JsViewPropTypeString,
.assign = (JsViewPropAssign)header_assign},
(JsViewPropDescriptor){
.name = "text",
.type = JsViewPropTypeString,
.assign = (JsViewPropAssign)text_assign},
(JsViewPropDescriptor){
.name = "left",
.type = JsViewPropTypeString,
.assign = (JsViewPropAssign)left_assign},
(JsViewPropDescriptor){
.name = "center",
.type = JsViewPropTypeString,
.assign = (JsViewPropAssign)center_assign},
(JsViewPropDescriptor){
.name = "right",
.type = JsViewPropTypeString,
.assign = (JsViewPropAssign)right_assign},
}};
JS_GUI_VIEW_DEF(dialog, &view_descriptor);