[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 21:42:11 +03:00
|
|
|
#include "../../js_modules.h" // IWYU pragma: keep
|
|
|
|
|
#include "js_gui.h"
|
|
|
|
|
#include "../js_event_loop/js_event_loop.h"
|
|
|
|
|
#include <gui/modules/submenu.h>
|
|
|
|
|
|
|
|
|
|
#define QUEUE_LEN 2
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
FuriMessageQueue* queue;
|
|
|
|
|
JsEventLoopContract contract;
|
|
|
|
|
} JsSubmenuCtx;
|
|
|
|
|
|
|
|
|
|
static mjs_val_t choose_transformer(struct mjs* mjs, FuriMessageQueue* queue, void* context) {
|
|
|
|
|
UNUSED(context);
|
|
|
|
|
uint32_t index;
|
|
|
|
|
furi_check(furi_message_queue_get(queue, &index, 0) == FuriStatusOk);
|
|
|
|
|
return mjs_mk_number(mjs, (double)index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void choose_callback(void* context, uint32_t index) {
|
|
|
|
|
JsSubmenuCtx* ctx = context;
|
|
|
|
|
furi_check(furi_message_queue_put(ctx->queue, &index, 0) == FuriStatusOk);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
header_assign(struct mjs* mjs, Submenu* submenu, JsViewPropValue value, void* context) {
|
|
|
|
|
UNUSED(mjs);
|
|
|
|
|
UNUSED(context);
|
|
|
|
|
submenu_set_header(submenu, value.string);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool items_assign(struct mjs* mjs, Submenu* submenu, JsViewPropValue value, void* context) {
|
|
|
|
|
UNUSED(mjs);
|
|
|
|
|
submenu_reset(submenu);
|
2024-10-31 05:22:05 +00:00
|
|
|
size_t len = mjs_array_length(mjs, value.term);
|
[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 21:42:11 +03:00
|
|
|
for(size_t i = 0; i < len; i++) {
|
2024-10-31 05:22:05 +00:00
|
|
|
mjs_val_t item = mjs_array_get(mjs, value.term, i);
|
[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 21:42:11 +03:00
|
|
|
if(!mjs_is_string(item)) return false;
|
|
|
|
|
submenu_add_item(submenu, mjs_get_string(mjs, &item, NULL), i, choose_callback, context);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static JsSubmenuCtx* ctx_make(struct mjs* mjs, Submenu* input, mjs_val_t view_obj) {
|
|
|
|
|
UNUSED(input);
|
|
|
|
|
JsSubmenuCtx* context = malloc(sizeof(JsSubmenuCtx));
|
|
|
|
|
context->queue = furi_message_queue_alloc(QUEUE_LEN, sizeof(uint32_t));
|
|
|
|
|
context->contract = (JsEventLoopContract){
|
|
|
|
|
.magic = JsForeignMagic_JsEventLoopContract,
|
|
|
|
|
.object_type = JsEventLoopObjectTypeQueue,
|
|
|
|
|
.object = context->queue,
|
|
|
|
|
.non_timer =
|
|
|
|
|
{
|
|
|
|
|
.event = FuriEventLoopEventIn,
|
|
|
|
|
.transformer = (JsEventLoopTransformer)choose_transformer,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
mjs_set(mjs, view_obj, "chosen", ~0, mjs_mk_foreign(mjs, &context->contract));
|
|
|
|
|
return context;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ctx_destroy(Submenu* input, JsSubmenuCtx* 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)submenu_alloc,
|
|
|
|
|
.free = (JsViewFree)submenu_free,
|
|
|
|
|
.get_view = (JsViewGetView)submenu_get_view,
|
|
|
|
|
.custom_make = (JsViewCustomMake)ctx_make,
|
|
|
|
|
.custom_destroy = (JsViewCustomDestroy)ctx_destroy,
|
|
|
|
|
.prop_cnt = 2,
|
|
|
|
|
.props = {
|
|
|
|
|
(JsViewPropDescriptor){
|
|
|
|
|
.name = "header",
|
|
|
|
|
.type = JsViewPropTypeString,
|
|
|
|
|
.assign = (JsViewPropAssign)header_assign},
|
|
|
|
|
(JsViewPropDescriptor){
|
|
|
|
|
.name = "items",
|
|
|
|
|
.type = JsViewPropTypeArr,
|
|
|
|
|
.assign = (JsViewPropAssign)items_assign},
|
|
|
|
|
}};
|
|
|
|
|
JS_GUI_VIEW_DEF(submenu, &view_descriptor);
|