From fa3b4781e1bb6ee70c4337c657c6470706b11d05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=AB=8B=E5=B8=AE?= <3294713004@qq.com> Date: Thu, 6 Mar 2025 18:20:50 +0800 Subject: [PATCH] =?UTF-8?q?Update:=20win7=E6=94=AF=E6=8C=81=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E4=BD=BF=E7=94=A8Serial=E5=92=8CHID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/modules/mixly-modules/common/app.js | 3 - common/modules/mixly-modules/common/serial.js | 12 ++ common/modules/mixly-modules/deps.json | 9 +- .../modules/mixly-modules/web/burn-upload.js | 12 +- common/modules/mixly-modules/web/hid.js | 28 +-- common/modules/mixly-modules/web/serial.js | 199 +++++++++++++----- .../modules/mixly-modules/web/serialport.js | 26 +-- common/modules/mixly-modules/web/usb-mini.js | 26 +-- common/modules/mixly-modules/web/usb.js | 26 +-- common/msg/mixly/en.json | 7 +- common/msg/mixly/zh-hans.json | 7 +- common/msg/mixly/zh-hant.json | 7 +- .../templates/html/devices-select-layer.html | 42 ++++ 13 files changed, 277 insertions(+), 127 deletions(-) create mode 100644 common/templates/html/devices-select-layer.html diff --git a/common/modules/mixly-modules/common/app.js b/common/modules/mixly-modules/common/app.js index bf5a0347..e0d3690d 100644 --- a/common/modules/mixly-modules/common/app.js +++ b/common/modules/mixly-modules/common/app.js @@ -239,9 +239,6 @@ class App extends Component { id: 'command-burn-btn', displayText: Msg.Lang['nav.btn.burn'], preconditionFn: () => { - if (!goog.isElectron && !goog.hasSocketServer && Serial.type !== 'serialport') { - return false; - } return SELECTED_BOARD?.nav?.burn; }, callback: () => BU.initBurn(), diff --git a/common/modules/mixly-modules/common/serial.js b/common/modules/mixly-modules/common/serial.js index 7b43d4c5..b394f69f 100644 --- a/common/modules/mixly-modules/common/serial.js +++ b/common/modules/mixly-modules/common/serial.js @@ -2,6 +2,7 @@ goog.loadJs('common', () => { goog.require('Mixly.Config'); goog.require('Mixly.Events'); +goog.require('Mixly.Registry'); goog.require('Mixly.Nav'); goog.require('Mixly.Msg'); goog.provide('Mixly.Serial'); @@ -9,6 +10,7 @@ goog.provide('Mixly.Serial'); const { Config, Events, + Registry, Nav, Msg } = Mixly; @@ -19,6 +21,8 @@ const { SELECTED_BOARD } = Config; class Serial { static { this.portsName = []; + this.portToNameRegistry = new Registry(); + this.nameToPortRegistry = new Registry(); this.DEFAULT_CONFIG = { ctrlCBtn: false, ctrlDBtn: false, @@ -42,6 +46,14 @@ class Serial { return this.portsName; } + this.refreshPorts = function () { + let portsName = []; + for (let name of Serial.nameToPortRegistry.keys()) { + portsName.push({ name }); + } + Serial.renderSelectBox(portsName); + } + this.getConfig = function () { let config = SELECTED_BOARD?.serial ?? {}; return { diff --git a/common/modules/mixly-modules/deps.json b/common/modules/mixly-modules/deps.json index 7c5d8689..f90fa53a 100644 --- a/common/modules/mixly-modules/deps.json +++ b/common/modules/mixly-modules/deps.json @@ -840,6 +840,7 @@ "require": [ "Mixly.Config", "Mixly.Events", + "Mixly.Registry", "Mixly.Nav", "Mixly.Msg" ], @@ -1626,7 +1627,6 @@ "path": "/web/hid.js", "require": [ "Mixly.Serial", - "Mixly.Registry", "Mixly.Web" ], "provide": [ @@ -1636,8 +1636,14 @@ { "path": "/web/serial.js", "require": [ + "path", "Mixly.Config", "Mixly.Env", + "Mixly.Msg", + "Mixly.Registry", + "Mixly.Serial", + "Mixly.LayerExt", + "Mixly.HTMLTemplate", "Mixly.Web.SerialPort", "Mixly.Web.USB", "Mixly.Web.USBMini", @@ -1651,7 +1657,6 @@ "path": "/web/serialport.js", "require": [ "Mixly.Serial", - "Mixly.Registry", "Mixly.Debug", "Mixly.Web" ], diff --git a/common/modules/mixly-modules/web/burn-upload.js b/common/modules/mixly-modules/web/burn-upload.js index fba7f4ac..48a91b4f 100644 --- a/common/modules/mixly-modules/web/burn-upload.js +++ b/common/modules/mixly-modules/web/burn-upload.js @@ -249,11 +249,15 @@ BU.burnWithEsptool = async (binFile, erase) => { return; } } + const port = Serial.getPort(portName); + if (port instanceof window.HIDDevice || port instanceof window.USBDevice) { + layer.msg(Msg.Lang['burn.notSupport'], { time: 1000 }); + return; + } const statusBarSerial = mainStatusBarTabs.getStatusBarById(portName); if (statusBarSerial) { await statusBarSerial.close(); } - const port = Serial.getPort(portName); const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output'); statusBarTerminal.setValue(Msg.Lang['shell.burning'] + '...\n'); mainStatusBarTabs.show(); @@ -365,11 +369,15 @@ BU.burnWithAdafruitEsptool = async (binFile, erase) => { return; } } + const port = Serial.getPort(portName); + if (port instanceof window.HIDDevice || port instanceof window.USBDevice) { + layer.msg(Msg.Lang['burn.notSupport'], { time: 1000 }); + return; + } const statusBarSerial = mainStatusBarTabs.getStatusBarById(portName); if (statusBarSerial) { await statusBarSerial.close(); } - const port = Serial.getPort(portName); const statusBarTerminal = mainStatusBarTabs.getStatusBarById('output'); statusBarTerminal.setValue(Msg.Lang['shell.burning'] + '...\n'); mainStatusBarTabs.show(); diff --git a/common/modules/mixly-modules/web/hid.js b/common/modules/mixly-modules/web/hid.js index 09261f7f..b07896df 100644 --- a/common/modules/mixly-modules/web/hid.js +++ b/common/modules/mixly-modules/web/hid.js @@ -1,13 +1,11 @@ goog.loadJs('web', () => { goog.require('Mixly.Serial'); -goog.require('Mixly.Registry'); goog.require('Mixly.Web'); goog.provide('Mixly.Web.HID'); const { Serial, - Registry, Web } = Mixly; @@ -15,8 +13,6 @@ const { class WebHID extends Serial { static { this.type = 'hid'; - this.portToNameRegistry = new Registry(); - this.nameToPortRegistry = new Registry(); this.getConfig = function () { return Serial.getConfig(); @@ -31,11 +27,7 @@ class WebHID extends Serial { } this.refreshPorts = function () { - let portsName = []; - for (let name of this.nameToPortRegistry.keys()) { - portsName.push({ name }); - } - Serial.renderSelectBox(portsName); + Serial.refreshPorts();; } this.requestPort = async function () { @@ -52,35 +44,35 @@ class WebHID extends Serial { } this.getPort = function (name) { - return this.nameToPortRegistry.getItem(name); + return Serial.nameToPortRegistry.getItem(name); } this.addPort = function (device) { - if (this.portToNameRegistry.hasKey(device)) { + if (Serial.portToNameRegistry.hasKey(device)) { return; } let name = ''; for (let i = 1; i <= 20; i++) { name = `hid${i}`; - if (this.nameToPortRegistry.hasKey(name)) { + if (Serial.nameToPortRegistry.hasKey(name)) { continue; } break; } - this.portToNameRegistry.register(device, name); - this.nameToPortRegistry.register(name, device); + Serial.portToNameRegistry.register(device, name); + Serial.nameToPortRegistry.register(name, device); } this.removePort = function (device) { - if (!this.portToNameRegistry.hasKey(device)) { + if (!Serial.portToNameRegistry.hasKey(device)) { return; } - const name = this.portToNameRegistry.getItem(device); + const name = Serial.portToNameRegistry.getItem(device); if (!name) { return; } - this.portToNameRegistry.unregister(device); - this.nameToPortRegistry.unregister(name); + Serial.portToNameRegistry.unregister(device); + Serial.nameToPortRegistry.unregister(name); } this.addEventsListener = function () { diff --git a/common/modules/mixly-modules/web/serial.js b/common/modules/mixly-modules/web/serial.js index 72faac16..b17035ee 100644 --- a/common/modules/mixly-modules/web/serial.js +++ b/common/modules/mixly-modules/web/serial.js @@ -1,14 +1,29 @@ goog.loadJs('web', () => { +goog.require('path'); goog.require('Mixly.Config'); goog.require('Mixly.Env'); +goog.require('Mixly.Msg'); +goog.require('Mixly.Registry'); +goog.require('Mixly.Serial'); +goog.require('Mixly.LayerExt'); +goog.require('Mixly.HTMLTemplate'); goog.require('Mixly.Web.SerialPort'); goog.require('Mixly.Web.USB'); goog.require('Mixly.Web.USBMini'); goog.require('Mixly.Web.HID'); goog.provide('Mixly.Web.Serial'); -const { Config, Env, Web } = Mixly; +const { + Config, + Env, + Msg, + Registry, + Serial, + LayerExt, + HTMLTemplate, + Web +} = Mixly; const { SerialPort, @@ -19,86 +34,164 @@ const { const { BOARD } = Config; -let Device = SerialPort; const platform = goog.platform(); const fullPlatform = goog.fullPlatform(); -if (platform === 'win32' && fullPlatform !== 'win10') { - if (BOARD?.web?.devices?.hid) { - Device = HID; - } else if (BOARD?.web?.devices?.serial) { - Device = SerialPort; - } else if (BOARD?.web?.devices?.usb) { - if (['BBC micro:bit', 'Mithon CC'].includes(BOARD.boardType)) { - Device = USB; - } else { - Device = USBMini; - } - } -} else if (platform === 'mobile') { - if (['BBC micro:bit', 'Mithon CC'].includes(BOARD.boardType)) { - Device = USB; - } else { - Device = USBMini; - } -} else { - if (BOARD?.web?.devices?.serial) { - Device = SerialPort; - } else if (BOARD?.web?.devices?.usb) { - if (['BBC micro:bit', 'Mithon CC'].includes(BOARD.boardType)) { - Device = USB; - } else { - Device = USBMini; - } - } else if (BOARD?.web?.devices?.hid) { - Device = HID; - } -} - -class WebSerial extends Device { +class WebSerial extends Serial { static { - this.type = Device.type; + this.devicesRegistry = new Registry(); + this.type = Serial.type; + this.DEVICES_SELECT_LAYER = new HTMLTemplate( + goog.get(path.join(Env.templatePath, 'html/devices-select-layer.html')) + ); this.getConfig = function () { - return Device.getConfig(); + return Serial.getConfig(); } this.getSelectedPortName = function () { - return Device.getSelectedPortName(); + return Serial.getSelectedPortName(); } this.getCurrentPortsName = function () { - return Device.getCurrentPortsName(); + return Serial.getCurrentPortsName(); } this.refreshPorts = function () { - return Device.refreshPorts(); + Serial.refreshPorts(); } - this.requestPort = async function () { - return Device.requestPort(); + this.requestPort = function () { + if (this.devicesRegistry.length() < 1) { + throw Error('can not find any device handler'); + } else if (this.devicesRegistry.length() === 1) { + const keys = this.devicesRegistry.keys(); + return this.devicesRegistry.getItem(keys[0]).requestPort(); + } + const msg = { + serialMsg: Msg.Lang['layer.devices.serial'], + serialStatus: this.devicesRegistry.hasKey('serial') ? '' : 'disabled', + hidMsg: Msg.Lang['layer.devices.hid'], + hidStatus: this.devicesRegistry.hasKey('hid') ? '' : 'disabled', + usbMsg: Msg.Lang['layer.devices.usb'], + usbStatus: ( + this.devicesRegistry.hasKey('usb') || this.devicesRegistry.hasKey('usbmini') + ) ? '' : 'disabled' + }; + return new Promise((resolve, reject) => { + let selected = false; + const layerNum = LayerExt.open({ + title: [Msg.Lang['layer.devices.select'], '36px'], + area: ['400px', '150px'], + max: false, + min: false, + content: this.DEVICES_SELECT_LAYER.render(msg), + shade: LayerExt.SHADE_ALL, + resize: false, + success: function (layero, index) { + $(layero).on('click', 'button', (event) => { + selected = true; + layer.close(layerNum); + const $btn = $(event.currentTarget); + let mId = $btn.attr('m-id'); + if (mId === 'usb' && WebSerial.devicesRegistry.hasKey('usbmini')) { + mId = 'usbmini'; + } + const Device = WebSerial.devicesRegistry.getItem(mId); + Device.requestPort().then(resolve).catch(reject); + }); + }, + end: function () { + if (!selected) { + reject('user not select any device'); + } + $(`#layui-layer-shade${layerNum}`).remove(); + } + }); + }); + } + + this.getHandler = function (device) { + if (device instanceof window.SerialPort) { + return SerialPort; + } else if (device instanceof window.HIDDevice) { + return HID; + } else if (device instanceof window.USBDevice) { + if (this.devicesRegistry.hasKey('usbmini')) { + return USBMini; + } else { + return USB; + } + } + return null; } this.getPort = function (name) { - return Device.getPort(name); + return Serial.nameToPortRegistry.getItem(name); } this.addPort = function (device) { - return Device.addPort(device); + const handler = this.getHandler(device); + if (!handler) { + return; + } + handler.addPort(device); } this.removePort = function (device) { - return Device.removePort(device); + const handler = this.getHandler(device); + if (!handler) { + return; + } + handler.removePort(device); } - this.addEventsListener = function () { - return Device.addEventsListener(); - } + this.addEventsListener = function () {} this.init = function () { - if (!Env.hasSocketServer) { - Device.init(); + if (Env.hasSocketServer) { + return; + } + if (platform === 'win32' && fullPlatform !== 'win10') { + if (BOARD?.web?.devices?.hid) { + this.devicesRegistry.register('hid', HID); + HID.init(); + } + if (BOARD?.web?.devices?.serial) { + this.devicesRegistry.register('serial', SerialPort); + SerialPort.init(); + } + if (BOARD?.web?.devices?.usb) { + if (['BBC micro:bit', 'Mithon CC'].includes(BOARD.boardType)) { + this.devicesRegistry.register('usb', USB); + USB.init(); + } + } + } else if (platform === 'mobile') { + if (['BBC micro:bit', 'Mithon CC'].includes(BOARD.boardType)) { + this.devicesRegistry.register('usb', USB); + USB.init(); + } else { + this.devicesRegistry.register('usbmini', USBMini); + USBMini.init(); + } + } else { + if (BOARD?.web?.devices?.serial) { + this.devicesRegistry.register('serial', SerialPort); + SerialPort.init(); + } else if (BOARD?.web?.devices?.usb) { + if (['BBC micro:bit', 'Mithon CC'].includes(BOARD.boardType)) { + this.devicesRegistry.register('usb', USB); + USB.init(); + } else { + this.devicesRegistry.register('usbmini', USBMini); + USBMini.init(); + } + } else if (BOARD?.web?.devices?.hid) { + this.devicesRegistry.register('hid', HID); + HID.init(); + } } } @@ -107,6 +200,12 @@ class WebSerial extends Device { constructor(port) { super(port); + const device = WebSerial.getPort(port); + const handler = WebSerial.getHandler(device); + if (!handler) { + return; + } + return new handler(port); } } diff --git a/common/modules/mixly-modules/web/serialport.js b/common/modules/mixly-modules/web/serialport.js index 15717c0a..5bdf373c 100644 --- a/common/modules/mixly-modules/web/serialport.js +++ b/common/modules/mixly-modules/web/serialport.js @@ -1,14 +1,12 @@ goog.loadJs('web', () => { goog.require('Mixly.Serial'); -goog.require('Mixly.Registry'); goog.require('Mixly.Debug'); goog.require('Mixly.Web'); goog.provide('Mixly.Web.SerialPort'); const { Serial, - Registry, Debug, Web } = Mixly; @@ -17,8 +15,6 @@ const { class WebSerialPort extends Serial { static { this.type = 'serialport'; - this.portToNameRegistry = new Registry(); - this.nameToPortRegistry = new Registry(); this.getConfig = function () { return Serial.getConfig(); @@ -33,11 +29,7 @@ class WebSerialPort extends Serial { } this.refreshPorts = function () { - let portsName = []; - for (let name of this.nameToPortRegistry.keys()) { - portsName.push({ name }); - } - Serial.renderSelectBox(portsName); + Serial.refreshPorts();; } this.requestPort = async function () { @@ -47,7 +39,7 @@ class WebSerialPort extends Serial { } this.getPort = function (name) { - return this.nameToPortRegistry.getItem(name); + return Serial.nameToPortRegistry.getItem(name); } this.addPort = function (serialport) { @@ -57,25 +49,25 @@ class WebSerialPort extends Serial { let name = ''; for (let i = 1; i <= 20; i++) { name = `serial${i}`; - if (this.nameToPortRegistry.hasKey(name)) { + if (Serial.nameToPortRegistry.hasKey(name)) { continue; } break; } - this.portToNameRegistry.register(serialport, name); - this.nameToPortRegistry.register(name, serialport); + Serial.portToNameRegistry.register(serialport, name); + Serial.nameToPortRegistry.register(name, serialport); } this.removePort = function (serialport) { - if (!this.portToNameRegistry.hasKey(serialport)) { + if (!Serial.portToNameRegistry.hasKey(serialport)) { return; } - const name = this.portToNameRegistry.getItem(serialport); + const name = Serial.portToNameRegistry.getItem(serialport); if (!name) { return; } - this.portToNameRegistry.unregister(serialport); - this.nameToPortRegistry.unregister(name); + Serial.portToNameRegistry.unregister(serialport); + Serial.nameToPortRegistry.unregister(name); } this.addEventsListener = function () { diff --git a/common/modules/mixly-modules/web/usb-mini.js b/common/modules/mixly-modules/web/usb-mini.js index 65635bca..2df0c679 100644 --- a/common/modules/mixly-modules/web/usb-mini.js +++ b/common/modules/mixly-modules/web/usb-mini.js @@ -14,9 +14,7 @@ const { class USBMini extends Serial { static { this.type = 'usb'; - this.portToNameRegistry = new Registry(); this.serialNumberToNameRegistry = new Registry(); - this.nameToPortRegistry = new Registry(); this.getConfig = function () { return Serial.getConfig(); @@ -31,11 +29,7 @@ class USBMini extends Serial { } this.refreshPorts = function () { - let portsName = []; - for (let name of this.nameToPortRegistry.keys()) { - portsName.push({ name }); - } - Serial.renderSelectBox(portsName); + Serial.refreshPorts();; } this.requestPort = async function () { @@ -47,11 +41,11 @@ class USBMini extends Serial { } this.getPort = function (name) { - return this.nameToPortRegistry.getItem(name); + return Serial.nameToPortRegistry.getItem(name); } this.addPort = function (device) { - if (this.portToNameRegistry.hasKey(device)) { + if (Serial.portToNameRegistry.hasKey(device)) { return; } const { serialNumber } = device; @@ -59,27 +53,27 @@ class USBMini extends Serial { if (!name) { for (let i = 1; i <= 20; i++) { name = `usb${i}`; - if (this.nameToPortRegistry.hasKey(name)) { + if (Serial.nameToPortRegistry.hasKey(name)) { continue; } break; } this.serialNumberToNameRegistry.register(serialNumber, name); } - this.portToNameRegistry.register(device, name); - this.nameToPortRegistry.register(name, device); + Serial.portToNameRegistry.register(device, name); + Serial.nameToPortRegistry.register(name, device); } this.removePort = function (device) { - if (!this.portToNameRegistry.hasKey(device)) { + if (!Serial.portToNameRegistry.hasKey(device)) { return; } - const name = this.portToNameRegistry.getItem(device); + const name = Serial.portToNameRegistry.getItem(device); if (!name) { return; } - this.portToNameRegistry.unregister(device); - this.nameToPortRegistry.unregister(name); + Serial.portToNameRegistry.unregister(device); + Serial.nameToPortRegistry.unregister(name); } this.addEventsListener = function () { diff --git a/common/modules/mixly-modules/web/usb.js b/common/modules/mixly-modules/web/usb.js index 53f73f51..5bc13e0b 100644 --- a/common/modules/mixly-modules/web/usb.js +++ b/common/modules/mixly-modules/web/usb.js @@ -15,9 +15,7 @@ const { class USB extends Serial { static { this.type = 'usb'; - this.portToNameRegistry = new Registry(); this.serialNumberToNameRegistry = new Registry(); - this.nameToPortRegistry = new Registry(); this.getConfig = function () { return Serial.getConfig(); @@ -32,11 +30,7 @@ class USB extends Serial { } this.refreshPorts = function () { - let portsName = []; - for (let name of this.nameToPortRegistry.keys()) { - portsName.push({ name }); - } - Serial.renderSelectBox(portsName); + Serial.refreshPorts();; } this.requestPort = async function () { @@ -48,11 +42,11 @@ class USB extends Serial { } this.getPort = function (name) { - return this.nameToPortRegistry.getItem(name); + return Serial.nameToPortRegistry.getItem(name); } this.addPort = function (device) { - if (this.portToNameRegistry.hasKey(device)) { + if (Serial.portToNameRegistry.hasKey(device)) { return; } const { serialNumber } = device; @@ -60,27 +54,27 @@ class USB extends Serial { if (!name) { for (let i = 1; i <= 20; i++) { name = `usb${i}`; - if (this.nameToPortRegistry.hasKey(name)) { + if (Serial.nameToPortRegistry.hasKey(name)) { continue; } break; } this.serialNumberToNameRegistry.register(serialNumber, name); } - this.portToNameRegistry.register(device, name); - this.nameToPortRegistry.register(name, device); + Serial.portToNameRegistry.register(device, name); + Serial.nameToPortRegistry.register(name, device); } this.removePort = function (device) { - if (!this.portToNameRegistry.hasKey(device)) { + if (!Serial.portToNameRegistry.hasKey(device)) { return; } - const name = this.portToNameRegistry.getItem(device); + const name = Serial.portToNameRegistry.getItem(device); if (!name) { return; } - this.portToNameRegistry.unregister(device); - this.nameToPortRegistry.unregister(name); + Serial.portToNameRegistry.unregister(device); + Serial.nameToPortRegistry.unregister(name); } this.addEventsListener = function () { diff --git a/common/msg/mixly/en.json b/common/msg/mixly/en.json index 6be33e33..63c089ee 100644 --- a/common/msg/mixly/en.json +++ b/common/msg/mixly/en.json @@ -389,5 +389,10 @@ "libManager.empty": "No data", "wiki.home": "Homepage", "wiki.pageNotFound": "Wiki page not found", - "wiki.open": "Open Wiki" + "wiki.open": "Open Wiki", + "layer.devices.serial": "Add Serial device", + "layer.devices.hid": "Add HID device", + "layer.devices.usb": "Add USB device", + "layer.devices.select": "Select device", + "burn.notSupport": "Unable to flash firmware with this device" } \ No newline at end of file diff --git a/common/msg/mixly/zh-hans.json b/common/msg/mixly/zh-hans.json index 95eab850..90c71f97 100644 --- a/common/msg/mixly/zh-hans.json +++ b/common/msg/mixly/zh-hans.json @@ -389,5 +389,10 @@ "libManager.empty": "无数据", "wiki.home": "首页", "wiki.pageNotFound": "未找到Wiki页", - "wiki.open": "打开Wiki" + "wiki.open": "打开Wiki", + "layer.devices.serial": "添加Serial设备", + "layer.devices.hid": "添加HID设备", + "layer.devices.usb": "添加USB设备", + "layer.devices.select": "选择设备", + "burn.notSupport": "无法使用此设备烧录固件" } \ No newline at end of file diff --git a/common/msg/mixly/zh-hant.json b/common/msg/mixly/zh-hant.json index 4402bc94..24b013e6 100644 --- a/common/msg/mixly/zh-hant.json +++ b/common/msg/mixly/zh-hant.json @@ -389,5 +389,10 @@ "libManager.empty": "無資料", "wiki.home": "首頁", "wiki.pageNotFound": "未找到Wiki頁", - "wiki.open": "開啟Wiki" + "wiki.open": "開啟Wiki", + "layer.devices.serial": "新增Serial裝置", + "layer.devices.hid": "新增HID裝置", + "layer.devices.usb": "新增USB裝置", + "layer.devices.select": "選擇裝置", + "burn.notSupport": "無法使用此設備燒錄固件" } \ No newline at end of file diff --git a/common/templates/html/devices-select-layer.html b/common/templates/html/devices-select-layer.html new file mode 100644 index 00000000..22689a2d --- /dev/null +++ b/common/templates/html/devices-select-layer.html @@ -0,0 +1,42 @@ + +
+ + + +
\ No newline at end of file