diff --git a/0-transpile.sh b/0-transpile.sh
index 4af87b6..bfe388f 100755
--- a/0-transpile.sh
+++ b/0-transpile.sh
@@ -1,4 +1,4 @@
#!/bin/sh
cd www
-npx tsc --allowJs --outFile main.comp.js polyfill.js i18n-ext.js i18n.js image.js accessibility.js main.js
+npx tsc $@ --allowJs --outFile main.comp.js $(cat all_js.txt)
cd ..
diff --git a/printer.py b/printer.py
index 57f92ac..145ef4e 100644
--- a/printer.py
+++ b/printer.py
@@ -364,11 +364,10 @@ class PrinterDriver(Commander):
elif (identifier not in Models and
identifier[2::3] != ':::::' and len(identifier.replace('-', '')) != 32):
error('model-0-is-not-supported-yet', identifier, exception=PrinterError)
- scanner = BleakScanner()
+ # scanner = BleakScanner()
devices = self.loop(
- scanner.discover(self.scan_timeout)
+ BleakScanner.discover(self.scan_timeout)
)
- devices = [dev for dev in devices if dev.name in Models]
if identifier is not None:
if identifier in Models:
devices = [dev for dev in devices if dev.name == identifier]
@@ -694,7 +693,7 @@ def main():
'Run the `_main` routine while catching exceptions'
try:
_main()
- except (BleakError, AttributeError) as e:
+ except BleakError as e:
error_message = str(e)
if (
('not turned on' in error_message) or # windows or android
@@ -702,15 +701,15 @@ def main():
getattr(e, 'dbus_error') == 'org.bluez.Error.NotReady')
):
fatal(I18n['please-enable-bluetooth'], code=ExitCodes.GeneralError)
- elif (
- (isinstance(e, AttributeError) and # macos, possibly?
- 'CentralManagerDelegate' in error_message)
- ):
- fatal(I18n['please-enable-bluetooth-or-try-to-reboot'], code=ExitCodes.GeneralError)
else:
raise
except PrinterError as e:
fatal(e.message_localized, code=ExitCodes.PrinterError)
+ except RuntimeError as e:
+ if 'no running event loop' in str(e):
+ pass # non-sense
+ else:
+ raise
if __name__ == '__main__':
main()
diff --git a/server.py b/server.py
index 5bc5863..e1a6efa 100644
--- a/server.py
+++ b/server.py
@@ -46,6 +46,13 @@ def mime(url: str):
'Get pre-defined MIME type of a certain url by extension name'
return mime_type.get(url.rsplit('.', 1)[-1], mime_type['octet-stream'])
+def concat_files(*paths, prefix_format='', buffer=4 * 1024 * 1024):
+ for path in paths:
+ yield prefix_format.format(path).encode('utf-8')
+ with open(path, 'rb') as file:
+ while data := file.read(buffer):
+ yield data
+
class PrinterServerHandler(BaseHTTPRequestHandler):
'(Local) server handler for Cat Printer Web interface'
@@ -64,6 +71,7 @@ class PrinterServerHandler(BaseHTTPRequestHandler):
_settings_blacklist = (
'printer', 'is_android'
)
+ all_js: list = []
printer: PrinterDriver = PrinterDriver()
@@ -84,17 +92,31 @@ class PrinterServerHandler(BaseHTTPRequestHandler):
pass
def do_GET(self):
- 'Called when server get a GET http request'
- path = 'www' + self.path
- if self.path == '/':
- path += 'index.html'
- if '/..' in path:
+ 'Called when server got a GET http request'
+ # prepare
+ path, _, _args = self.path.partition('?')
+ if '/..' in path or '../' in path:
return
+ if path == '/':
+ path += 'index.html'
+ # special
+ if path.startswith('/~'):
+ action = path[2:]
+ if action == 'every.js':
+ self.send_response(200)
+ self.send_header('Content-Type', mime(path))
+ self.end_headers()
+ for data in concat_files(*(self.all_js), prefix_format='\n// {0}\n'):
+ self.wfile.write(data)
+ return
+ path = 'www' + path
+ # not found
if not os.path.isfile(path):
self.send_response(404)
self.send_header('Content-Type', mime('txt'))
self.end_headers()
return
+ # static
self.send_response(200)
self.send_header('Content-Type', mime(path))
# self.send_header('Content-Size', str(os.stat(path).st_size))
@@ -214,7 +236,7 @@ class PrinterServerHandler(BaseHTTPRequestHandler):
sys.exit(0)
def do_POST(self):
- 'Called when server get a POST http request'
+ 'Called when server got a POST http request'
content_length = int(self.headers.get('Content-Length', -1))
if (content_length < -1 or
content_length > self.max_payload
@@ -239,16 +261,22 @@ class PrinterServerHandler(BaseHTTPRequestHandler):
'name': 'BleakError',
'details': str(e)
})
+ except EOFError as e:
+ # mostly, device disconnected but not by this program
+ self.api_fail({
+ 'name': 'EOFError',
+ 'details': ''
+ })
+ except RuntimeError as e:
+ self.api_fail({
+ 'name': 'RuntimeError',
+ 'details': str(e)
+ })
except PrinterError as e:
self.api_fail({
'name': e.message,
'details': e.message_localized
})
- except EOFError as e:
- self.api_fail({
- 'name': 'EOFError',
- 'details': ''
- })
except Exception as e:
self.api_fail({
'name': 'Exception',
@@ -272,6 +300,10 @@ class PrinterServer(HTTPServer):
def finish_request(self, request, client_address):
if self.handler is None:
self.handler = self.handler_class(request, client_address, self)
+ with open(os.path.join('www', 'all_js.txt'), 'r', encoding='utf-8') as file:
+ for path in file.read().split('\n'):
+ if path != '':
+ self.handler.all_js.append(os.path.join('www', path))
return
self.handler.__init__(request, client_address, self)
diff --git a/version b/version
index 60a2d3e..44bb5d1 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.4.0
\ No newline at end of file
+0.4.1
\ No newline at end of file
diff --git a/www/accessibility.js b/www/accessibility.js
index 7a152fd..01b9327 100644
--- a/www/accessibility.js
+++ b/www/accessibility.js
@@ -39,22 +39,30 @@ function keyToLetter(key) {
return map[key] || key;
}
+function keyFromCode(code) {
+ const map = {
+ 9: 'Tab'
+ };
+ return map[code] || String.fromCharCode(code);
+}
+
function initKeyboardShortcuts() {
const layer = document.getElementById('keyboard-shortcuts-layer');
const dialog = document.getElementById('dialog');
const keys = 'qwertyuiopasdfghjklzxcvbnm';
let focusing = false, started = false;
let shortcuts = {};
- let key, focus, inputs;
+ let focus, inputs;
const mark_keys = () => {
- let index;
+ document.querySelectorAll(':focus').forEach(e => e.isSameNode(focus) || e.blur());
+ let index, key;
if (dialog.classList.contains('hidden'))
inputs = Array.from(document.querySelectorAll('*[data-key]'));
else inputs = Array.from(document.querySelectorAll('#dialog *[data-key]'));
/** @type {{ [key: string]: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement }} */
let keys2 = keys.split('');
shortcuts = {};
- if (focusing) shortcuts = { ESC: focus };
+ if (focusing) shortcuts = { 'ESC': focus };
else
for (let input of inputs) {
if (isHidden(input)) continue;
@@ -69,14 +77,14 @@ function initKeyboardShortcuts() {
layer.appendChild(span);
}
index = 0;
- for (let key in shortcuts) {
+ for (key in shortcuts) {
let span = layer.children[index++];
let input = shortcuts[key];
let position = input.getBoundingClientRect();
let text = i18n(keyToLetter(key.toUpperCase()));
if (span.innerText !== text) span.innerText = text;
- span.style.top = position.y + 'px';
- span.style.left = position.x + 'px';
+ span.style.top = (position.y || position.top) + 'px';
+ span.style.left = (position.x || position.left) + 'px';
span.style.display = '';
}
for (let i = index; i < layer.children.length; i++) {
@@ -86,17 +94,15 @@ function initKeyboardShortcuts() {
const start = () => setInterval(mark_keys, 1000);
const types_to_click = ['submit', 'file', 'checkbox', 'radio', 'A'];
document.body.addEventListener('keyup', (event) => {
- key = event.key;
+ let key = event.key || keyFromCode(event.keyCode);
if (!started) {
if (key !== 'Tab') return;
mark_keys();
start();
started = true;
}
- document.body.addEventListener('keyup', () =>
- requestAnimationFrame(mark_keys)
- , { once: true });
- let input = shortcuts[key.toLocaleLowerCase()];
+ requestAnimationFrame(mark_keys)
+ let input = shortcuts[key];
if (input) {
if (types_to_click.includes(input.type || input.tagName))
input.dispatchEvent(new MouseEvent(event.shiftKey ? 'contextmenu' : 'click'));
@@ -105,7 +111,7 @@ function initKeyboardShortcuts() {
focusing = true;
}
focus = input;
- } else if (key === 'Escape' && focus) {
+ } else if ((key === 'Escape' || !event.isTrusted) && focus) {
focus.blur();
focusing = !focusing;
}
diff --git a/www/all_js.txt b/www/all_js.txt
new file mode 100644
index 0000000..4c34244
--- /dev/null
+++ b/www/all_js.txt
@@ -0,0 +1,6 @@
+polyfill.js
+i18n-ext.js
+i18n.js
+image.js
+accessibility.js
+main.js
diff --git a/www/index.html b/www/index.html
index 1d81dcf..c9dc057 100644
--- a/www/index.html
+++ b/www/index.html
@@ -46,7 +46,7 @@
-->
-
+
diff --git a/www/jslicense.html b/www/jslicense.html
index b6e8c8a..d75caa5 100644
--- a/www/jslicense.html
+++ b/www/jslicense.html
@@ -26,6 +26,18 @@