mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-11-26 10:26:09 +03:00
implement byte input, add missing args in text input
TODO: add missing filebrowser dialog
This commit is contained in:
parent
8233534d6a
commit
004d8382d3
@ -66,6 +66,14 @@ App(
|
|||||||
sources=["modules/js_gui/text_input.c"],
|
sources=["modules/js_gui/text_input.c"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
App(
|
||||||
|
appid="js_gui__byte_input",
|
||||||
|
apptype=FlipperAppType.PLUGIN,
|
||||||
|
entry_point="js_view_byte_input_ep",
|
||||||
|
requires=["js_app", "js_gui", "js_event_loop"],
|
||||||
|
sources=["modules/js_gui/byte_input.c"],
|
||||||
|
)
|
||||||
|
|
||||||
App(
|
App(
|
||||||
appid="js_gui__text_box",
|
appid="js_gui__text_box",
|
||||||
apptype=FlipperAppType.PLUGIN,
|
apptype=FlipperAppType.PLUGIN,
|
||||||
|
130
applications/system/js_app/modules/js_gui/byte_input.c
Normal file
130
applications/system/js_app/modules/js_gui/byte_input.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#include "../../js_modules.h" // IWYU pragma: keep
|
||||||
|
#include "js_gui.h"
|
||||||
|
#include "../js_event_loop/js_event_loop.h"
|
||||||
|
#include <gui/modules/byte_input.h>
|
||||||
|
|
||||||
|
#define DEFAULT_BUF_SZ 4
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t* buffer;
|
||||||
|
size_t buffer_size;
|
||||||
|
FuriString* header;
|
||||||
|
FuriSemaphore* input_semaphore;
|
||||||
|
JsEventLoopContract contract;
|
||||||
|
} JsByteKbContext;
|
||||||
|
|
||||||
|
static mjs_val_t
|
||||||
|
input_transformer(struct mjs* mjs, FuriSemaphore* semaphore, JsByteKbContext* context) {
|
||||||
|
furi_check(furi_semaphore_acquire(semaphore, 0) == FuriStatusOk);
|
||||||
|
return mjs_mk_array_buf(mjs, (char*)context->buffer, context->buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void input_callback(JsByteKbContext* context) {
|
||||||
|
furi_semaphore_release(context->input_semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool header_assign(
|
||||||
|
struct mjs* mjs,
|
||||||
|
ByteInput* input,
|
||||||
|
JsViewPropValue value,
|
||||||
|
JsByteKbContext* context) {
|
||||||
|
UNUSED(mjs);
|
||||||
|
furi_string_set(context->header, value.string);
|
||||||
|
byte_input_set_header_text(input, furi_string_get_cstr(context->header));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
len_assign(struct mjs* mjs, ByteInput* input, JsViewPropValue value, JsByteKbContext* context) {
|
||||||
|
UNUSED(mjs);
|
||||||
|
UNUSED(input);
|
||||||
|
context->buffer_size = (size_t)(value.number);
|
||||||
|
context->buffer = realloc(context->buffer, context->buffer_size); //-V701
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool default_data_assign(
|
||||||
|
struct mjs* mjs,
|
||||||
|
ByteInput* input,
|
||||||
|
JsViewPropValue value,
|
||||||
|
JsByteKbContext* context) {
|
||||||
|
UNUSED(mjs);
|
||||||
|
|
||||||
|
if(mjs_is_data_view(value.array)) {
|
||||||
|
value.array = mjs_dataview_get_buf(mjs, value.array);
|
||||||
|
}
|
||||||
|
size_t default_data_len = 0;
|
||||||
|
char* default_data = mjs_array_buf_get_ptr(mjs, value.array, &default_data_len);
|
||||||
|
memcpy(
|
||||||
|
context->buffer,
|
||||||
|
(uint8_t*)default_data,
|
||||||
|
MIN((size_t)context->buffer_size, default_data_len));
|
||||||
|
|
||||||
|
byte_input_set_result_callback(
|
||||||
|
input,
|
||||||
|
(ByteInputCallback)input_callback,
|
||||||
|
NULL,
|
||||||
|
context,
|
||||||
|
context->buffer,
|
||||||
|
context->buffer_size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JsByteKbContext* ctx_make(struct mjs* mjs, ByteInput* input, mjs_val_t view_obj) {
|
||||||
|
UNUSED(input);
|
||||||
|
JsByteKbContext* context = malloc(sizeof(JsByteKbContext));
|
||||||
|
*context = (JsByteKbContext){
|
||||||
|
.buffer_size = DEFAULT_BUF_SZ,
|
||||||
|
.buffer = malloc(DEFAULT_BUF_SZ),
|
||||||
|
.header = furi_string_alloc(),
|
||||||
|
.input_semaphore = furi_semaphore_alloc(1, 0),
|
||||||
|
};
|
||||||
|
context->contract = (JsEventLoopContract){
|
||||||
|
.magic = JsForeignMagic_JsEventLoopContract,
|
||||||
|
.object_type = JsEventLoopObjectTypeSemaphore,
|
||||||
|
.object = context->input_semaphore,
|
||||||
|
.non_timer =
|
||||||
|
{
|
||||||
|
.event = FuriEventLoopEventIn,
|
||||||
|
.transformer = (JsEventLoopTransformer)input_transformer,
|
||||||
|
.transformer_context = context,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
UNUSED(mjs);
|
||||||
|
UNUSED(view_obj);
|
||||||
|
mjs_set(mjs, view_obj, "input", ~0, mjs_mk_foreign(mjs, &context->contract));
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ctx_destroy(ByteInput* input, JsByteKbContext* context, FuriEventLoop* loop) {
|
||||||
|
UNUSED(input);
|
||||||
|
furi_event_loop_maybe_unsubscribe(loop, context->input_semaphore);
|
||||||
|
furi_semaphore_free(context->input_semaphore);
|
||||||
|
furi_string_free(context->header);
|
||||||
|
free(context->buffer);
|
||||||
|
free(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JsViewDescriptor view_descriptor = {
|
||||||
|
.alloc = (JsViewAlloc)byte_input_alloc,
|
||||||
|
.free = (JsViewFree)byte_input_free,
|
||||||
|
.get_view = (JsViewGetView)byte_input_get_view,
|
||||||
|
.custom_make = (JsViewCustomMake)ctx_make,
|
||||||
|
.custom_destroy = (JsViewCustomDestroy)ctx_destroy,
|
||||||
|
.prop_cnt = 3,
|
||||||
|
.props = {
|
||||||
|
(JsViewPropDescriptor){
|
||||||
|
.name = "header",
|
||||||
|
.type = JsViewPropTypeString,
|
||||||
|
.assign = (JsViewPropAssign)header_assign},
|
||||||
|
(JsViewPropDescriptor){
|
||||||
|
.name = "length",
|
||||||
|
.type = JsViewPropTypeNumber,
|
||||||
|
.assign = (JsViewPropAssign)len_assign},
|
||||||
|
(JsViewPropDescriptor){
|
||||||
|
.name = "defaultData",
|
||||||
|
.type = JsViewPropTypeTypedArr,
|
||||||
|
.assign = (JsViewPropAssign)default_data_assign},
|
||||||
|
}};
|
||||||
|
|
||||||
|
JS_GUI_VIEW_DEF(byte_input, &view_descriptor);
|
@ -215,6 +215,20 @@ static bool
|
|||||||
}
|
}
|
||||||
c_value = (JsViewPropValue){.array = value};
|
c_value = (JsViewPropValue){.array = value};
|
||||||
} break;
|
} break;
|
||||||
|
case JsViewPropTypeTypedArr: {
|
||||||
|
if(!mjs_is_typed_array(value)) {
|
||||||
|
expected_type = "typed_array";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c_value = (JsViewPropValue){.array = value};
|
||||||
|
} break;
|
||||||
|
case JsViewPropTypeBool: {
|
||||||
|
if(!mjs_is_boolean(value)) {
|
||||||
|
expected_type = "bool";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c_value = (JsViewPropValue){.boolean = mjs_get_bool(mjs, value)};
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(expected_type) {
|
if(expected_type) {
|
||||||
|
@ -9,12 +9,15 @@ typedef enum {
|
|||||||
JsViewPropTypeString,
|
JsViewPropTypeString,
|
||||||
JsViewPropTypeNumber,
|
JsViewPropTypeNumber,
|
||||||
JsViewPropTypeArr,
|
JsViewPropTypeArr,
|
||||||
|
JsViewPropTypeTypedArr,
|
||||||
|
JsViewPropTypeBool,
|
||||||
} JsViewPropType;
|
} JsViewPropType;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
const char* string;
|
const char* string;
|
||||||
int32_t number;
|
int32_t number;
|
||||||
mjs_val_t array;
|
mjs_val_t array;
|
||||||
|
bool boolean;
|
||||||
} JsViewPropValue;
|
} JsViewPropValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,15 +48,40 @@ static bool max_len_assign(
|
|||||||
JsViewPropValue value,
|
JsViewPropValue value,
|
||||||
JsKbdContext* context) {
|
JsKbdContext* context) {
|
||||||
UNUSED(mjs);
|
UNUSED(mjs);
|
||||||
|
UNUSED(input);
|
||||||
context->buffer_size = (size_t)(value.number + 1);
|
context->buffer_size = (size_t)(value.number + 1);
|
||||||
context->buffer = realloc(context->buffer, context->buffer_size); //-V701
|
context->buffer = realloc(context->buffer, context->buffer_size); //-V701
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool default_text_assign(
|
||||||
|
struct mjs* mjs,
|
||||||
|
TextInput* input,
|
||||||
|
JsViewPropValue value,
|
||||||
|
JsKbdContext* context) {
|
||||||
|
UNUSED(mjs);
|
||||||
|
UNUSED(input);
|
||||||
|
|
||||||
|
if(value.string) {
|
||||||
|
strlcpy(context->buffer, value.string, context->buffer_size);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool default_text_clear_assign(
|
||||||
|
struct mjs* mjs,
|
||||||
|
TextInput* input,
|
||||||
|
JsViewPropValue value,
|
||||||
|
JsKbdContext* context) {
|
||||||
|
UNUSED(mjs);
|
||||||
|
|
||||||
text_input_set_result_callback(
|
text_input_set_result_callback(
|
||||||
input,
|
input,
|
||||||
(TextInputCallback)input_callback,
|
(TextInputCallback)input_callback,
|
||||||
context,
|
context,
|
||||||
context->buffer,
|
context->buffer,
|
||||||
context->buffer_size,
|
context->buffer_size,
|
||||||
true);
|
value.boolean);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +126,7 @@ static const JsViewDescriptor view_descriptor = {
|
|||||||
.get_view = (JsViewGetView)text_input_get_view,
|
.get_view = (JsViewGetView)text_input_get_view,
|
||||||
.custom_make = (JsViewCustomMake)ctx_make,
|
.custom_make = (JsViewCustomMake)ctx_make,
|
||||||
.custom_destroy = (JsViewCustomDestroy)ctx_destroy,
|
.custom_destroy = (JsViewCustomDestroy)ctx_destroy,
|
||||||
.prop_cnt = 3,
|
.prop_cnt = 5,
|
||||||
.props = {
|
.props = {
|
||||||
(JsViewPropDescriptor){
|
(JsViewPropDescriptor){
|
||||||
.name = "header",
|
.name = "header",
|
||||||
@ -115,6 +140,14 @@ static const JsViewDescriptor view_descriptor = {
|
|||||||
.name = "maxLength",
|
.name = "maxLength",
|
||||||
.type = JsViewPropTypeNumber,
|
.type = JsViewPropTypeNumber,
|
||||||
.assign = (JsViewPropAssign)max_len_assign},
|
.assign = (JsViewPropAssign)max_len_assign},
|
||||||
|
(JsViewPropDescriptor){
|
||||||
|
.name = "defaultText",
|
||||||
|
.type = JsViewPropTypeString,
|
||||||
|
.assign = (JsViewPropAssign)default_text_assign},
|
||||||
|
(JsViewPropDescriptor){
|
||||||
|
.name = "defaultTextClear",
|
||||||
|
.type = JsViewPropTypeBool,
|
||||||
|
.assign = (JsViewPropAssign)default_text_clear_assign},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
JS_GUI_VIEW_DEF(text_input, &view_descriptor);
|
JS_GUI_VIEW_DEF(text_input, &view_descriptor);
|
||||||
|
Loading…
Reference in New Issue
Block a user