尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Unleashed 固件 JS SDK 开发指南:用 `gui/dialog` 模块构建三按钮交互对话框

Unleashed 固件 JS SDK 开发指南:用 `gui/dialog` 模块构建三按钮交互对话框 Unleashed 固件 JS SDK 开发指南用gui/dialog模块构建三按钮交互对话框【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmwareFlipper Zero Unleashed 固件内置了完整的 JavaScript 运行时与 JS SDK见 documentation/js/js_about.md开发者可以在设备上直接运行.js脚本实现图形界面。gui/dialog是 GUI 模块中负责询问用户的视图组件它在一屏内显示一段粗体标题、一段正文以及最多三个按钮用于确认、取消、三选一等典型交互场景。本文将围绕该模块的导入方式、属性Props、事件Event与事件循环订阅机制展开并结合仓库内 C 语言胶水实现与 TypeScript 类型声明给出可直接运行的实战示例。模块依赖与导入顺序gui/dialog是gui模块的子模块而gui又依赖event_loop模块因此导入顺序必须严格遵守且需要依次先理解这几个模块的职责let eventLoop require(event_loop); let gui require(gui); let dialogView require(gui/dialog);event_loop事件循环提供定时器、订阅等基础机制是 GUI 视图事件如按钮按下的转发通道guiGUI 模块持有全局唯一的viewDispatcher视图调度器单例负责视图切换与输入事件分发gui/dialogdialog 视图的工厂模块dialogView即一个ViewFactory。在源码层面这一依赖关系体现在 js_gui.c 的js_gui_create中gui模块创建时会通过js_module_get(modules, event_loop)取出事件循环对象并基于它创建view_dispatcher_alloc_ex(loop)而 dialog 模块的声明则位于 dialog.c由JS_GUI_VIEW_DEF(dialog, view_descriptor)宏展开为名为gui__dialog的 JS 模块描述符这也就是require(gui/dialog)最终命中的注册入口。建议在深入 dialog 之前先阅读 documentation/js/js_event_loop.md 与 documentation/js/js_gui.md理解 View / ViewFactory / ViewDispatcher 与事件订阅的协作方式。View 属性Propsdialog 视图的全部可配置属性都接收字符串值通过makeWith(props)在创建时注入或通过view.set(name, value)在运行期修改Prop类型说明headerstring屏幕顶部加粗显示的标题文本textstring屏幕中部显示的正文文本leftstring左按钮文本不设置则不渲染左按钮centerstring中按钮文本不设置则不渲染中按钮rightstring右按钮文本不设置则不渲染右按钮三个按钮属性均为可选任一按钮未设置文本对应按钮就不会出现。这在实现仅确认或确认/取消等非对称布局时非常实用。这些属性在 C 侧由 dialog.c 的view_descriptor声明prop_cnt 5与五个JsViewPropDescriptorheader、text、left、center、right一一对应每个属性类型均为JsViewPropTypeString。属性赋值会经js_gui_view_assign见 js_gui.c做类型校验如果传入的不是字符串会抛出view prop xxx requires string value错误。底层实现上dialog 视图包装的是 GUI 服务中的DialogEx模块见 dialog_ex.h。每个属性的赋值回调直接对应一个 C API 调用header→dialog_ex_set_header(dialog, text, 64, 0, AlignCenter, AlignTop)标题锚定屏幕顶部水平居中text→dialog_ex_set_text(dialog, text, 64, 32, AlignCenter, AlignCenter)正文锚定屏幕垂直居中位置left/center/right→dialog_ex_set_left_button_text/dialog_ex_set_center_button_text/dialog_ex_set_right_button_text。对齐与坐标由胶水代码固定开发者只需要关心文本内容本身。同时DialogEx的原生 API 还支持 icondialog_ex_set_icon与扩展按下/释放事件dialog_ex_enable_extended_events这些能力目前未在 JS 侧暴露。View 事件Eventdialog 视图只有一个事件源inputItem类型说明inputstring用户按下三个按钮中的任意一个时触发事件值为left、center或right之一对应所按按钮该事件是事件循环中的Contract对象创建于 dialog.c 的ctx_makedialog 视图被创建时分配一个容量为 2 的FuriMessageQueue注册DialogExResultCallback回调原生按钮按下事件通过input_callback写入消息队列再由input_transformer将DialogExResultLeft/Center/Right枚举映射为 JS 字符串left/center/right后交付给 JS 侧。这个契约对象被挂载为视图对象的input属性因此可以在eventLoop.subscribe(views.xxx.input, ...)中使用。注意DialogEx原生回调运行在 GUI 线程见 dialog_ex.h 的注释警告跨线程数据传递正是通过消息队列完成的这也是该实现能够与事件循环安全协作的原因。完整示例从事件循环订阅到按钮分发文档推荐的完整示例见仓库自带的gui.js演示脚本gui.js。该脚本同时展示了 dialog 的两种典型用法。1. 创建对话框并动态设置文本与按钮let helloDialog dialogView.make(); // 运行期更新正文与按钮 views.helloDialog.set(text, Hi name ! :)); views.helloDialog.set(center, Hi Flipper! :)); gui.viewDispatcher.switchTo(views.helloDialog);这里只设置center按钮因此屏幕上只出现一个居中按钮——典型的一键确认框。2. 订阅input事件分发按钮逻辑eventLoop.subscribe(views.helloDialog.input, function (_sub, button, gui, views) { if (button center) gui.viewDispatcher.switchTo(views.demos); }, gui, views);eventLoop.subscribe的第二个参数是回调函数第一个参数_sub为订阅对象第二个参数button即left/center/right之一从第三个参数开始是调用时透传的附加参数此处为gui与views由 subscribe 尾部实参传入回调据此可以访问gui.viewDispatcher进行视图切换。在此基础上一个完整的三按钮对话框可以这样写let eventLoop require(event_loop); let gui require(gui); let dialogView require(gui/dialog); let views { main: dialogView.makeWith({ header: Delete file?, text: This action cannot be undone, left: Cancel, center: Retry, right: Delete, }), done: dialogView.makeWith({ text: Done, center: OK }), }; eventLoop.subscribe(views.main.input, function (_sub, button, gui, views) { if (button left) { gui.viewDispatcher.switchTo(views.done); } else if (button center) { // 重试逻辑 } else if (button right) { // 删除逻辑 } gui.viewDispatcher.switchTo(views.done); }, gui, views); gui.viewDispatcher.switchTo(views.main); eventLoop.run();从 JS 到原生视图的完整调用链综合上述分析gui/dialog的完整实现链路可以概括为注册JS_GUI_VIEW_DEF(dialog, view_descriptor)宏js_gui.h将 dialog 注册为gui__dialog插件模块工厂模块加载时js_gui_make_view_factory生成带make/makeWith方法的ViewFactory对象js_gui.c实例化make()/makeWith()调用js_gui_make_view执行descriptor-alloc()即dialog_ex_alloc创建原生DialogEx将其加入viewDispatcher并分配视图 idmakeWith再逐条执行属性赋值js_gui.c渲染与输入dialog_ex_get_view返回的View被调度器接管按钮按下经DialogExResultCallback→ 消息队列 →input_transformer→ JS 字符串事件销毁视图被释放时js_gui_view_destructor依次调用custom_destroy释放队列、退订事件循环与descriptor-free即dialog_ex_free见 js_gui.c。对应当前仓库中 JS SDK 0.1 版本TypeScript 类型声明也完整描述了该模块的契约dialog.d.tsDialog类继承ViewProps, Child其中Child neverdialog 不支持子元素调用addChild/setChildren会报错 this View cant have childreninput: Contractleft | center | right与本文描述的事件语义完全一致。使用 JS SDKdocumentation/js/js_developing_apps_using_js_sdk.md开发时这些类型定义可以提供完整的代码补全与静态校验。小结dialog 视图适合作为确认框、提示框、三选一选择器最多支持三个按钮且按钮可按需省略导入顺序必须是event_loop→gui→gui/dialog属性在创建时通过makeWith({...})注入运行期通过view.set(prop, value)更新按钮点击通过view.input事件订阅消费事件值即left/center/right底层由 GUI 服务的DialogEx视图实现dialog_ex.cJS 胶水代码负责属性映射与线程安全的队列事件传递。【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表