mirror of
https://github.com/NaitLee/Cat-Printer.git
synced 2025-05-16 07:10:30 -07:00
better css; image rotation; lolcat i18n; update about
the works are still incomplete. expecting more code cleaning
This commit is contained in:
parent
947cb9a5b9
commit
502a572183
1
TODO
1
TODO
@ -12,6 +12,7 @@ Note: not ordered. do whatever I/you want
|
||||
+ Make a build guide for android:
|
||||
Summary the hacks to p4a, bleak p4a recipe, p4a webview bootstrap, and AdvancedWebView
|
||||
+ Try to implement enough without more dependencies
|
||||
+ More funny i18n
|
||||
+ Arch Linux package / AUR, package for other distros
|
||||
+ Service for other init systems (a systemd unit file is there)
|
||||
+ ...
|
||||
|
@ -153,3 +153,34 @@ That may involve another (partial) rewrite.
|
||||
Afraid not, experiment always worth it. And remember: it's all about idea, everyone can make use of then.
|
||||
|
||||
Yawn... bed time...
|
||||
|
||||
9th
|
||||
|
||||
Did some stylesheet fix.
|
||||
|
||||
Then go for image rotation. It shouldn't be that hard:
|
||||
|
||||
0 1 2 3 16 17 18 19 32 33 34 35 48 49 50 51
|
||||
4 5 6 7 20 21 22 23 36 37 38 39 52 53 54 55
|
||||
8 9 10 11 24 25 26 27 40 41 42 43 56 57 58 59
|
||||
12 13 14 15 28 29 30 31 44 45 46 47 60 61 62 63
|
||||
16 17 18 19 32 33 34 35 48 49 50 51 64 65 66 67
|
||||
20 21 22 23 36 37 38 39 52 53 54 55 68 69 70 71
|
||||
|
||||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
||||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
||||
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
||||
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
||||
|
||||
Think about HTML canvas ImageData, one dimensional [R,G,B,A,...] array.
|
||||
The "big" problem is just make a procedure to transform from the first matrix to the second.
|
||||
(and flip the result horizontally)
|
||||
|
||||
Know what happened? I produced a right procedure from very start, but the image screwed up.
|
||||
|
||||
Tried to "fix" it, used at least 4 hours, finally found it's a matter of didn't floor a floating number.
|
||||
(Height is got by multiplying aspect ratio)
|
||||
|
||||
So the Internet JavaScript memes are damned true.
|
||||
https://programmerhumor.io/javascript-memes/why-is-it-like-this-2/
|
||||
https://programmerhumor.io/javascript-memes/sorry-dad-_-2/
|
||||
|
@ -635,7 +635,7 @@ def _main():
|
||||
parser.add_argument('-f', '--fake', metavar='XY01', type=str, default='',
|
||||
help=i18n('virtual-run-on-specified-model'))
|
||||
parser.add_argument('-m', '--dump', action='store_true',
|
||||
help=i18n('dump-the-traffic'))
|
||||
help=i18n('dump-traffic'))
|
||||
parser.add_argument('-n', '--nothing', action='store_true',
|
||||
help=i18n('do-nothing'))
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
<a target="_blank" href="https://github.com/NaitLee">NaitLee</a>
|
||||
</dt>
|
||||
<dd data-i18n="developer">Developer</dd>
|
||||
<dd data-i18n="translator">Translator</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
@ -32,7 +33,19 @@
|
||||
<dd data-i18n="translator">Translator</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt data-i18n="all-testers-and-users">All testers & users</dt>
|
||||
<dt>
|
||||
<a target="_blank" href="https://github.com/andypiper">andypiper</a>
|
||||
</dt>
|
||||
<dd data-i18n="minor-tweaks">Minor Tweaks</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<a target="_blank" href="https://github.com/sync1211">sync1211</a>
|
||||
</dt>
|
||||
<dd data-i18n="developer">Developer</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt data-i18n="all-users-and-developers">All testers & users</dt>
|
||||
<dd data-i18n="everyone-is-awesome">Everyone is awesome!</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
@ -26,14 +26,14 @@
|
||||
<span class="label-span-input">
|
||||
<span data-i18n="process-as-">Process as:</span>
|
||||
<span>
|
||||
<label>
|
||||
<input type="radio" name="algo" value="algo-direct" data-key />
|
||||
<span data-i18n="text">Text</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="algo" value="algo-steinberg" data-key checked />
|
||||
<span data-i18n="picture">Picture</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="algo" value="algo-direct" data-key />
|
||||
<span data-i18n="text">Text</span>
|
||||
</label>
|
||||
</span>
|
||||
</span>
|
||||
<!-- "brightness" is historically "threshold" -->
|
||||
@ -52,6 +52,10 @@
|
||||
<input type="range" min="24" max="36" value="32" step="4" name="quality" data-key data-default />
|
||||
</label>
|
||||
</div>
|
||||
<label class="label-input-span">
|
||||
<input type="checkbox" name="rotate" data-key />
|
||||
<span data-i18n="rotate-image">Rotate Image</span>
|
||||
</label>
|
||||
<label class="label-input-span" data-hide-as="print">
|
||||
<input type="checkbox" name="transparent-as-white" data-key checked />
|
||||
<span data-i18n="transparent-as-white">Transparent as White</span>
|
||||
@ -120,7 +124,7 @@
|
||||
<div id="control-overlay">
|
||||
<div>
|
||||
<button id="insert-picture" data-i18n="insert-picture" data-key="Enter">Insert Picture</button>
|
||||
<button id="insert-text" data-i18n="insert-text" data-key="">Insert Text</button>
|
||||
<button id="insert-text" data-i18n="insert-text" data-key="\">Insert Text</button>
|
||||
<p data-i18n="or-drag-file-to-below" class="hide-on-android">Or drag file to below</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -131,7 +135,6 @@
|
||||
<div class="center buttons">
|
||||
<!-- <button id="canvas-expand" data-i18n="expand">Expand</button>
|
||||
<button id="canvas-crop" data-i18n="crop">Crop</button> -->
|
||||
<!-- <button id="button-preview" data-i18n="preview">Preview</button> -->
|
||||
<button id="button-reset" data-i18n="reset" data-key>Reset</button>
|
||||
<button id="button-print" data-i18n="print" data-key=" ">Print</button>
|
||||
</div>
|
||||
@ -141,6 +144,7 @@
|
||||
<div id="hidden" class="hard-hidden">
|
||||
<!-- Hidden area for putting elements -->
|
||||
<input type="file" id="file" />
|
||||
<img src="" id="img" alt="hidden-image" />
|
||||
<div id="accessibility">
|
||||
<div>
|
||||
<h2>
|
||||
@ -180,42 +184,37 @@
|
||||
<div id="text-input">
|
||||
<h1 data-i18n="insert-text">Insert Text</h1>
|
||||
<div>
|
||||
|
||||
<div id="text-settings">
|
||||
<div name="font-and-size" class="text-settings-group">
|
||||
|
||||
<select id="text-font">
|
||||
<option value="Arial">Arial (sans-serif)</option>
|
||||
<option value="Brush Script MT">Brush Script MT (cursive)</option>
|
||||
<option value="Courier New">Courier New (monospace)</option>
|
||||
<option value="Garamond">Garamond (serif)</option>
|
||||
<option value="Georgia">Georgia (serif)</option>
|
||||
<option value="Helvetica" selected>Helvetica (sans-serif)</option>
|
||||
<option value="Tahoma">Tahoma (sans-serif)</option>
|
||||
<option value="Times New Roman">Times New Roman (serif)</option>
|
||||
<option value="Trebuchet MS">Trebuchet MS (sans-serif)</option>
|
||||
<option value="Verdana">Verdana (sans-serif)</option>
|
||||
<select id="text-font" contenteditable="true" data-key>
|
||||
<option value="serif" data-i18n="serif">Serif</option>
|
||||
<option value="sans-serif" data-i18n="sans-serif" selected>Sans Serif</option>
|
||||
<option value="monospace" data-i18n="monospace">Monospace</option>
|
||||
<option value="Unifont" data-i18n="unifont">Unifont</option>
|
||||
</select>
|
||||
<input id="text-size" type="number" name="text-size" min="1" max="100" value="20" data-key style="margin: 0px;"/>
|
||||
</div>
|
||||
<div name="wrap-and-align" class="text-settings-group">
|
||||
<label data-i18n="wrap-by-space" name="wrap-by-space-label"><input type="checkbox" name="wrap-by-space" data-key checked />Wrap text</label>
|
||||
<label>
|
||||
<input type="checkbox" name="wrap-words-by-spaces" data-key checked />
|
||||
<span data-i18n="wrap-words-by-spaces">Wrap words by spaces</span>
|
||||
</label>
|
||||
<span class="text-align-container">
|
||||
<input type="radio" name="text-align" value="left" checked/>
|
||||
<input type="radio" name="text-align" value="left" data-key checked />
|
||||
<span class="text-align-checkmark text-align-left"></span>
|
||||
</span>
|
||||
<span class="text-align-container">
|
||||
<input type="radio" name="text-align" value="center"/>
|
||||
<input type="radio" name="text-align" value="center" data-key />
|
||||
<span class="text-align-checkmark text-align-center"></span>
|
||||
</span>
|
||||
<span class="text-align-container">
|
||||
<input type="radio" name="text-align" value="right"/>
|
||||
<input type="radio" name="text-align" value="right" data-key />
|
||||
<span class="text-align-checkmark text-align-right"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="text-textarea">
|
||||
<textarea id="insert-text-area"></textarea>
|
||||
<textarea id="insert-text-area" data-key="/"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -52,7 +52,6 @@
|
||||
"supported-models-": "Unterstützte Modelle:",
|
||||
"path-to-input-file-dash-for-stdin": "Pfad zur Datei. '-' für stdin",
|
||||
"scan-for-specified-seconds": "Suchlauf für die angegebenen Sekunden",
|
||||
"dump-the-traffic": "Den Datenverkehr auf dem Drucker ausgeben und PBM-Bild beim Textdruck",
|
||||
"text-printing-mode": "Textdruckmodus",
|
||||
"please-install-pyobjc-via-pip": "Bitte installieren Sie `pyobjc` über pip",
|
||||
"please-install-bleak-via-pip": "Bitte installieren Sie `bleak` über pip",
|
||||
@ -94,7 +93,7 @@
|
||||
"contributors": "Beitragende",
|
||||
"developer": "Entwickler",
|
||||
"translator": "Übersetzer",
|
||||
"all-testers-and-users": "All Tester & Benutzer",
|
||||
"all-users-and-developers": "All Tester & Benutzer",
|
||||
"everyone-is-awesome": "Jeder ist super",
|
||||
"license": "Lizenz",
|
||||
"exiting": "Exiting…",
|
||||
@ -107,5 +106,5 @@
|
||||
"text-font": "Schriftart",
|
||||
"text-size": "Textgröße",
|
||||
"enter-text": "Text eingeben",
|
||||
"wrap-by-space": "Autom. Zeilenumbruch"
|
||||
"wrap-words-by-spaces": "Autom. Zeilenumbruch"
|
||||
}
|
@ -91,7 +91,7 @@
|
||||
"contributors": "Contributors",
|
||||
"developer": "Developer",
|
||||
"translator": "Translator",
|
||||
"all-testers-and-users": "All testers & users",
|
||||
"all-users-and-developers": "All users & developers",
|
||||
"everyone-is-awesome": "Everyone is awesome!",
|
||||
"license": "License",
|
||||
"exiting": "Exiting…",
|
||||
@ -132,5 +132,10 @@
|
||||
"text-font": "Font",
|
||||
"text-size": "Size",
|
||||
"enter-text": "Enter text",
|
||||
"wrap-by-space": "Wrap words by spaces"
|
||||
"wrap-words-by-spaces": "Wrap words by spaces",
|
||||
"minor-tweaks": "Minor Tweaks",
|
||||
"serif": "Serif",
|
||||
"sans-serif": "Sans Serif",
|
||||
"monospace": "Monospace",
|
||||
"rotate-image": "Rotate Image"
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"en-US": "English (US)",
|
||||
"zh-CN": "中文(简体)",
|
||||
"de-DE": "Deutsch"
|
||||
"de-DE": "Deutsch",
|
||||
"lolcat": "LOLCAT"
|
||||
}
|
136
www/lang/lolcat.json
Normal file
136
www/lang/lolcat.json
Normal file
@ -0,0 +1,136 @@
|
||||
{
|
||||
"$language": "LOLCAT",
|
||||
"cat-printer": "KITTE PAWS 🐾",
|
||||
"printer": "PAWS",
|
||||
"device-": "KITTE>",
|
||||
"refresh": "FIND",
|
||||
"mode-": "HOW>",
|
||||
"canvas": "VIEW",
|
||||
"document": "DOC",
|
||||
"insert-picture": "PUT CAT PIC",
|
||||
"insert-text": "SAY MEOW",
|
||||
"help": "HALP",
|
||||
"javascript-license-information": "BROWSR JUNK",
|
||||
"settings": "CONFIGUR",
|
||||
"image": "PIC",
|
||||
"threshold-": "BLAK OR WHITE",
|
||||
"transparent-as-white": "DONT POLUT PIC",
|
||||
"misc": "OTHR",
|
||||
"system": "SYS",
|
||||
"disable-animation": "NO MOTION",
|
||||
"exit": "BAK TO HOM",
|
||||
"error-message": "SOMTHIN WRONG",
|
||||
"preview": "LOOK",
|
||||
"print": "PAW STEP",
|
||||
"expand": "MORE",
|
||||
"crop": "LESS",
|
||||
"scanning-for-devices": "LUKIN FOR KITTEZ",
|
||||
"scan-time-": "HOW LONG TO FIND",
|
||||
"-seconds": "SECS",
|
||||
"no-available-devices-found": "NO KITTE FOUND",
|
||||
"found-0-available-devices": {
|
||||
"single": "THER IS {0} KITTE",
|
||||
"multiple": "THER R {0} KITTEZ"
|
||||
},
|
||||
"please-check-if-the-printer-is-down": "CHEK IF KITTE IS SLIPIN",
|
||||
"printing": "KITTE WALKIN…",
|
||||
"finished": "K BYE!!",
|
||||
"coming-soon": "COMIN SOON…",
|
||||
"dry-run": "DONT STEP WITH INK",
|
||||
"dry-run-test-print-process-only": "WONT REILLY STEP NOW",
|
||||
"you-can-close-this-page-manually": "KITTE SLEP YA MAY GO",
|
||||
"please-enable-bluetooth": "OPEN YA BLUETOOTH PLZ",
|
||||
"error-happened-please-check-error-message": "SOMTHIN WRONG CHK ERR LOG PLZ",
|
||||
"you-can-seek-for-help-with-detailed-info-below": "ASK OTHR KITTE WITH THEZ",
|
||||
"or-try-to-scan-longer": "TRY TO FIND BIT LONGER",
|
||||
"print-to-cat-printer": "PAWS TO STEP ON PAPR OF KITTE PRINTER!",
|
||||
"supported-models-": "KNOWN KITTEZ>",
|
||||
"path-to-input-file-dash-for-stdin": "WHAT FILE TO STEP '-' MEAN STDIN",
|
||||
"please-install-pyobjc-via-pip": "INSTAL `pyobjc` VIA pip",
|
||||
"please-install-bleak-via-pip": "INSTAL `bleak` VIA pip",
|
||||
"folder-printer_lib-is-incomplete-or-missing-please-check": "DIR `printer_lib` HAV PROBLM CHK PLZ",
|
||||
"input-is-not-pbm-image": "INPUT ISNT PBM PIC",
|
||||
"unsuitable-image-width-expected-0-got-1": "WRONG PIC WIDZ {0} WANT {1}",
|
||||
"broken-pbm-image": "BAD PBM PIC",
|
||||
"input-is-not-text-file": "SAY MEOW MEOW NOT PIC",
|
||||
"match-printer-with-this-name-or-address": "PICK TIS KITTE NAM,ADDR",
|
||||
"virtual-run-on-specified-model": "DREAM ABOUT TIS KITTE YA DONT HAVE",
|
||||
"font-size-0": "PAW BIG AS {0}",
|
||||
"stopping": "LEAVIN",
|
||||
"connecting": "IM COMIN",
|
||||
"model-0-is-not-supported-yet": "KITTE '{0}' UNKNON",
|
||||
"invalid-address-0": "THER ISNT A KITTE AT '{0}'",
|
||||
"will-listen-on-all-addresses": "GATHER CONN ON ALL ADDRS",
|
||||
"serving-at-0": "IM AT {0}",
|
||||
"disconnecting-from-printer": "LEAVIN KITTE",
|
||||
"connected-to-0-1": "PICKD TIS {0} {1}",
|
||||
"flip-horizontally": "FLIP <>",
|
||||
"flip-vertically": "FLIP ^v",
|
||||
"dump-traffic": "WACH KITTE PAWS",
|
||||
"right-to-left-text-order": "YA READ RTL",
|
||||
"auto-wrap-line": "WRAP MEOW",
|
||||
"process-as-": "HOW TO STEP>",
|
||||
"text": "MEOW",
|
||||
"picture": "PICS",
|
||||
"pattern": "SPOTS",
|
||||
"large-font": "BIGGR PAW",
|
||||
"accessibility": "IM SPECIAL",
|
||||
"language": "WHAT YA SAY",
|
||||
"layout": "WHAT YA LOOK",
|
||||
"ok": "GO",
|
||||
"cancel": "BACK",
|
||||
"yes": "YEAH",
|
||||
"no": "NOPE",
|
||||
"about": "KITTE INFO",
|
||||
"home-page-": "CAT HOME>",
|
||||
"contributors": "GOOD PEEPL",
|
||||
"developer": "H4CKR",
|
||||
"translator": "LOLCAT",
|
||||
"all-users-and-developers": "ALL LITL N BIG CATS",
|
||||
"everyone-is-awesome": "YA LL AWSOM!!",
|
||||
"license": "SERIOS THINY",
|
||||
"exiting": "STOPIN…",
|
||||
|
||||
"dark-theme": "BLAK EYES",
|
||||
"high-contrast": "WEAK EYES",
|
||||
"welcome": "HAI THER!!",
|
||||
"copyright-and-license": "SERIOS THINY",
|
||||
"some-rights-reserved": "Some rights reserved.",
|
||||
"ENTER": "ENTR",
|
||||
"SPACE": "SPAC",
|
||||
"ESCAPE": "ESC",
|
||||
"TAB": "TAB",
|
||||
"COMMA": "COMA",
|
||||
"DOT": "DOT",
|
||||
"to-enter-keyboard-mode-press-tab": "KEYBORD G33KS PRES TAB",
|
||||
"usage-": "HOW TO USE>",
|
||||
"positional-arguments-": "ARGS>",
|
||||
"options-": "OPTS>",
|
||||
"show-this-help-message": "SHOW WHAT YA LOOKIN NOW",
|
||||
"do-nothing": "SLEEPY KITTE",
|
||||
"scan-for-a-printer": "FIND A KITTE",
|
||||
"text-printing-mode-with-options": "NO STEP PIC WANT MEOW",
|
||||
"image-printing-options": "HOW TO STEP A PIC",
|
||||
"convert-input-image-with-imagemagick": "HLP WITH ImageMagick",
|
||||
"reset-configuration-": "RLY SCREW CFG?",
|
||||
"brightness-": "BLAK OR WHITE>",
|
||||
"text-printing-mode": "MEOW MEOW",
|
||||
"internal-error-please-see-terminal": "ERR IN CONSOL PLZ SI",
|
||||
"control-printer-thermal-strength": "HOW MUCH INK",
|
||||
"strength-": "HOW MUCH INK>",
|
||||
"or-drag-file-to-below": "THRW PIC OR MEOW HERE",
|
||||
"reset": "STRT OVR",
|
||||
"cat-face-toward": "WANT KITTE FACE NOT BUTT",
|
||||
"quality-": "CAREFUL STEP>",
|
||||
"print-quality": "HOW CAREFUL R STEPS",
|
||||
"show-more-options": "LOT CFGS HERE",
|
||||
"text-font": "PAW SHAP",
|
||||
"text-size": "BIG OR SMAL",
|
||||
"enter-text": "MEOW HERE",
|
||||
"wrap-words-by-spaces": "NO HAF A WORD",
|
||||
"minor-tweaks": "LITTL TRIKS",
|
||||
"serif": "SHARP PAW",
|
||||
"sans-serif": "SOFT PAW",
|
||||
"monospace": "H4CKY PAW",
|
||||
"rotate-image": "ROLL PIC"
|
||||
}
|
@ -8,14 +8,12 @@
|
||||
"canvas": "画布",
|
||||
"document": "文档",
|
||||
"insert-picture": "插入图片",
|
||||
"insert-text": "输入文本",
|
||||
"help": "帮助",
|
||||
"javascript-license-information": "JavaScript 许可证信息",
|
||||
"settings": "设置",
|
||||
"image": "图像",
|
||||
"threshold-": "阈值:",
|
||||
"transmission-speed-": "传输速度:",
|
||||
"low": "低",
|
||||
"moderate": "适中",
|
||||
"high": "高",
|
||||
"transparent-as-white": "透明为白色",
|
||||
"misc": "杂项",
|
||||
"system": "系统",
|
||||
@ -45,7 +43,6 @@
|
||||
"print-to-cat-printer": "打印到猫咪打印机。",
|
||||
"supported-models-": "支持的型号:",
|
||||
"path-to-input-file-dash-for-stdin": "输入文件的位置。使用 '-' 作为标准输入",
|
||||
"dump-the-traffic": "转储数据",
|
||||
"please-install-pyobjc-via-pip": "请从 pip 安装 `pyobjc`",
|
||||
"please-install-bleak-via-pip": "请从 pip 安装 `bleak`",
|
||||
"folder-printer_lib-is-incomplete-or-missing-please-check": "文件夹 `printer_lib` 不完整或丢失,请检查",
|
||||
@ -85,7 +82,7 @@
|
||||
"contributors": "贡献者",
|
||||
"developer": "开发者",
|
||||
"translator": "翻译",
|
||||
"all-testers-and-users": "所有测试及正式用户",
|
||||
"all-users-and-developers": "每位用户及开发者",
|
||||
"everyone-is-awesome": "每个人都是好样的!",
|
||||
"license": "许可证",
|
||||
"exiting": "退出中……",
|
||||
@ -122,5 +119,14 @@
|
||||
"cat-face-toward": "猫脸朝上",
|
||||
"quality-": "质量:",
|
||||
"print-quality": "打印质量",
|
||||
"show-more-options": "显示更多选项"
|
||||
"show-more-options": "显示更多选项",
|
||||
"text-font": "字体",
|
||||
"text-size": "大小",
|
||||
"enter-text": "在此处输入文本",
|
||||
"wrap-words-by-spaces": "空格处换行(不建议用于汉语)",
|
||||
"minor-tweaks": "小优化",
|
||||
"serif": "衬线字体",
|
||||
"sans-serif": "无衬线字体",
|
||||
"monospace": "等宽字体",
|
||||
"rotate-image": "旋转图像"
|
||||
}
|
81
www/main.css
81
www/main.css
@ -36,6 +36,9 @@ body {
|
||||
margin: 1em 0;
|
||||
user-select: none;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body.android .hide-on-android {
|
||||
display: none;
|
||||
}
|
||||
@ -90,9 +93,12 @@ input[type="number"], input[type="text"] {
|
||||
cursor: text;
|
||||
}
|
||||
button:hover {
|
||||
/*
|
||||
margin: 0;
|
||||
padding: var(--span) var(--span-double);
|
||||
min-width: calc(6em + var(--span-double));
|
||||
*/
|
||||
transform: scale(1.1);
|
||||
}
|
||||
button:active {
|
||||
box-shadow: 0 0 var(--span) inset var(--fore-color);
|
||||
@ -103,7 +109,6 @@ button:active {
|
||||
}
|
||||
.label-span-input {
|
||||
display: table-row;
|
||||
box-sizing: border-box;
|
||||
margin: var(--span-half) var(--span);
|
||||
}
|
||||
.label-span-input>:nth-child(1) {
|
||||
@ -119,7 +124,6 @@ button:active {
|
||||
}
|
||||
.label-input-span {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
margin: var(--span-half) var(--span);
|
||||
}
|
||||
.label-input-span>:nth-child(1) {
|
||||
@ -173,11 +177,14 @@ main, header, footer {
|
||||
max-width: 45em;
|
||||
margin: 1em auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.canvas-side {
|
||||
flex-grow: 0;
|
||||
min-width: calc(var(--paper-width) + var(--border-double) + var(--span-double));
|
||||
width: var(--paper-width);
|
||||
margin: var(--span) calc((50% - var(--paper-width)) / 2);
|
||||
}
|
||||
.canvas-side>* {
|
||||
text-align: center;
|
||||
@ -188,8 +195,9 @@ main, header, footer {
|
||||
top: 0;
|
||||
height: 100%;
|
||||
/* overflow: auto; */
|
||||
margin: var(--span);
|
||||
min-width: 12em;
|
||||
margin: var(--span) 0;
|
||||
min-width: 20em;
|
||||
/* width: 50%; */
|
||||
}
|
||||
.menu-side>.menu {
|
||||
border: var(--border) solid var(--fore-color);
|
||||
@ -216,6 +224,7 @@ main, header, footer {
|
||||
margin: 0;
|
||||
}
|
||||
.compact-button:hover {
|
||||
transform: unset;
|
||||
margin: 0;
|
||||
padding: 0 var(--span) calc(var(--span-double));
|
||||
min-width: 6em;
|
||||
@ -249,9 +258,9 @@ main, header, footer {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
display: inline-block;
|
||||
width: calc(var(--paper-width) + var(--border-double));
|
||||
margin: var(--span);
|
||||
margin-bottom: 0;
|
||||
/* width: calc(var(--paper-width) + var(--border-double)); */
|
||||
width: var(--paper-width);
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
p {
|
||||
margin: var(--span) 0;
|
||||
@ -263,7 +272,6 @@ p {
|
||||
.panel.active {
|
||||
height: calc(var(--panel-height) - var(--compact-menu-height));
|
||||
padding: var(--span-double) var(--span);
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.panel.sub.active {
|
||||
@ -313,6 +321,11 @@ table#jslicense-labels1 {
|
||||
}
|
||||
table#jslicense-labels1 td {
|
||||
padding: var(--span-half) var(--span);
|
||||
white-space: nowrap;
|
||||
}
|
||||
table#jslicense-labels1 td:nth-child(4) {
|
||||
white-space: normal;
|
||||
width: 50vw;
|
||||
}
|
||||
*:target {
|
||||
background-color: var(--target-color);
|
||||
@ -335,7 +348,7 @@ hr {
|
||||
}
|
||||
iframe#frame {
|
||||
width: 100%;
|
||||
height: 12em;
|
||||
height: 60vh;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
@ -355,33 +368,32 @@ iframe#frame {
|
||||
#dialog {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: 16%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
text-align: center;
|
||||
z-index: 2;
|
||||
opacity: 2;
|
||||
opacity: 1;
|
||||
transition: opacity var(--anim-time) var(--curve);
|
||||
}
|
||||
#dialog>.content {
|
||||
max-width: 100%;
|
||||
width: 40em;
|
||||
margin: auto;
|
||||
box-sizing: border-box;
|
||||
width: 42em;
|
||||
max-height: 80vh;
|
||||
margin: 12vh auto;
|
||||
border: var(--border) solid var(--fore-color);
|
||||
transition: transform var(--anim-time) var(--curve);
|
||||
transform-origin: center 33%;
|
||||
}
|
||||
#dialog.hidden {
|
||||
opacity: 0;
|
||||
height: unset;
|
||||
}
|
||||
#dialog.hidden>.content {
|
||||
transform: scaleY(0);
|
||||
}
|
||||
#dialog-content {
|
||||
/* height: 12em; */
|
||||
max-height: 640px;
|
||||
max-height: 60vh;
|
||||
margin: auto;
|
||||
padding: var(--span);
|
||||
padding: var(--span-double);
|
||||
padding-bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -405,12 +417,12 @@ iframe#frame {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#select-language {
|
||||
width: calc(100% - var(--span-double));
|
||||
/* width: calc(100% - var(--span-double)); */
|
||||
width: 12em;
|
||||
height: 8em;
|
||||
border: var(--border) solid var(--fore-color);
|
||||
padding: var(--span);
|
||||
margin: 0 var(--span);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#select-language option {
|
||||
cursor: pointer;
|
||||
@ -438,7 +450,7 @@ iframe#frame {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
z-index: 1;
|
||||
z-index: 3;
|
||||
opacity: 1;
|
||||
transition: opacity var(--anim-time) var(--curve);
|
||||
}
|
||||
@ -467,7 +479,7 @@ iframe#frame {
|
||||
height: var(--font-size);
|
||||
margin: var(--font-size);
|
||||
background-color: var(--fore-color);
|
||||
border-radius: calc(var(--font-size) / 2);
|
||||
border-radius: var(--font-size);
|
||||
animation: jump 1s ease 0s infinite;
|
||||
}
|
||||
#loading-screen>.dots>span:nth-child(1) { animation-delay: 0s; }
|
||||
@ -519,6 +531,7 @@ a {
|
||||
#title { display: none; }
|
||||
.canvas-side {
|
||||
min-width: unset;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
@ -530,7 +543,7 @@ a {
|
||||
.canvas-side>.buttons,
|
||||
.menu-side>.buttons {
|
||||
position: sticky;
|
||||
bottom: var(--compact-menu-height);
|
||||
bottom: var(--span);
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
@ -570,6 +583,9 @@ a {
|
||||
width: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
#dialog-content {
|
||||
padding: var(--span) 0;
|
||||
}
|
||||
.blank {
|
||||
height: var(--compact-menu-height);
|
||||
}
|
||||
@ -656,19 +672,22 @@ body.high-contrast #notice * { border: var(--border) dashed var(--fore-color); }
|
||||
body.high-contrast a:any-link { color: #00f; }
|
||||
body.high-contrast #control-overlay { background-color: var(--shade); }
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: 'Unifont';
|
||||
src: local('Unifont') url('unifont.ttf') url('unifont.otf');
|
||||
}
|
||||
*/
|
||||
#insert-text-area {
|
||||
white-space: pre;
|
||||
height: 50vh;
|
||||
width: var(--paper-width);
|
||||
overflow: hidden auto;
|
||||
white-space: pre;
|
||||
height: calc(60vh - 8em);
|
||||
width: var(--paper-width);
|
||||
overflow: hidden auto;
|
||||
white-space: break-spaces;
|
||||
resize:none;
|
||||
resize: none;
|
||||
padding-top: .65ex;
|
||||
line-height: 1.25;
|
||||
border: var(--border) solid currentColor;
|
||||
}
|
||||
|
||||
.text-align-container span {
|
||||
@ -703,7 +722,7 @@ body.high-contrast #control-overlay { background-color: var(--shade); }
|
||||
.text-align-center { background-image: url("icons/text-center.svg")}
|
||||
.text-align-right { background-image: url("icons/text-right.svg")}
|
||||
|
||||
input[name="wrap-by-space"] { margin-right: 5px; }
|
||||
input[name="wrap-words-by-spaces"] { margin-right: 5px; }
|
||||
#text-settings {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -715,5 +734,5 @@ input[name="wrap-by-space"] { margin-right: 5px; }
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
label[name="wrap-by-space-label"] { padding-right: 2%; }
|
||||
label[name="wrap-words-by-spaces-label"] { padding-right: 2%; }
|
||||
#text-font { height: 100%; margin: 0px; }
|
244
www/main.js
244
www/main.js
@ -274,32 +274,38 @@ class CanvasController {
|
||||
canvas;
|
||||
imageUrl;
|
||||
algorithm;
|
||||
_height;
|
||||
_threshold;
|
||||
_energy;
|
||||
_thresholdRange;
|
||||
_energyRange;
|
||||
algoElements;
|
||||
textFont;
|
||||
textSize;
|
||||
textArea;
|
||||
transparentAsWhite;
|
||||
previewData;
|
||||
rotate;
|
||||
#height;
|
||||
#threshold;
|
||||
#energy;
|
||||
#thresholdRange;
|
||||
#energyRange;
|
||||
#rotateCheck;
|
||||
static defaultHeight = 384;
|
||||
static defaultThreshold = 256 / 3;
|
||||
get threshold() {
|
||||
return this._threshold;
|
||||
return this.#threshold;
|
||||
}
|
||||
set threshold(value) {
|
||||
this._threshold = this._thresholdRange.value = value;
|
||||
this.#threshold = this.#thresholdRange.value = value;
|
||||
}
|
||||
get energy() {
|
||||
return this._energy;
|
||||
return this.#energy;
|
||||
}
|
||||
set energy(value) {
|
||||
this._energy = this._energyRange.value = value;
|
||||
this.#energy = this.#energyRange.value = value;
|
||||
}
|
||||
get height() {
|
||||
return this._height;
|
||||
return this.#height;
|
||||
}
|
||||
set height(value) {
|
||||
this.canvas.height = this.preview.height = this._height = value;
|
||||
this.canvas.height = this.preview.height = this.#height = value;
|
||||
}
|
||||
constructor() {
|
||||
this.preview = document.getElementById('preview');
|
||||
@ -308,13 +314,13 @@ class CanvasController {
|
||||
this.textSize = document.getElementById("text-size");
|
||||
this.textFont = document.getElementById("text-font");
|
||||
this.textArea = document.getElementById("insert-text-area");
|
||||
this.wrapBySpace = document.querySelector('input[name="wrap-by-space"]');
|
||||
this.textAlgorithm = document.querySelector('input[name="algo"][value="algo-direct"]');
|
||||
this.wrapBySpace = document.querySelector('input[name="wrap-words-by-spaces"]');
|
||||
this.height = CanvasController.defaultHeight;
|
||||
this._thresholdRange = document.querySelector('[name="threshold"]');
|
||||
this._energyRange = document.querySelector('[name="energy"]');
|
||||
this.#thresholdRange = document.querySelector('[name="threshold"]');
|
||||
this.#energyRange = document.querySelector('[name="energy"]');
|
||||
this.imageUrl = null;
|
||||
this.textAlign = "left";
|
||||
this.textAlign = "left";
|
||||
this.rotate = false;
|
||||
|
||||
for (let elem of document.querySelectorAll("input[name=text-align]")){
|
||||
if (elem.checked) { this.textAlign = elem.value; }
|
||||
@ -336,7 +342,7 @@ class CanvasController {
|
||||
};
|
||||
file_reader.readAsText(event.dataTransfer.files[0]);
|
||||
} else {
|
||||
this.insertPicture(event.dataTransfer.files);
|
||||
this.useFiles(event.dataTransfer.files);
|
||||
}
|
||||
return prevent_default(event);
|
||||
});
|
||||
@ -345,8 +351,10 @@ class CanvasController {
|
||||
this.textArea.style["font-family"] = this.textFont.value;
|
||||
this.textArea.style["word-break"] = this.wrapBySpace.checked ? "break-word" : "break-all";
|
||||
|
||||
this.algoElements = document.querySelectorAll('input[name="algo"]');
|
||||
|
||||
putEvent('input[name="algo"]', 'change', (event) => this.useAlgorithm(event.currentTarget.value), this);
|
||||
putEvent('#insert-picture' , 'click', () => this.insertPicture(), this);
|
||||
putEvent('#insert-picture' , 'click', () => this.useFiles(), this);
|
||||
putEvent('#insert-text' , 'click', () => Dialog.alert("#text-input", () => this.insertText(this.textArea.value)));
|
||||
putEvent('#text-size' , 'change', () => this.textArea.style["font-size"] = this.textSize.value + "px");
|
||||
putEvent('#text-font' , 'change', () => this.textArea.style["font-family"] = this.textFont.value);
|
||||
@ -354,11 +362,13 @@ class CanvasController {
|
||||
this.textAlign = event.currentTarget.value
|
||||
this.textArea.style["text-align"] = this.textAlign;
|
||||
}, this);
|
||||
putEvent('input[name="wrap-by-space"]' , 'change', () => this.textArea.style["word-break"] = this.wrapBySpace.checked ? "break-word" : "break-all");
|
||||
putEvent('input[name="wrap-words-by-spaces"]' , 'change', () => this.textArea.style["word-break"] = this.wrapBySpace.checked ? "break-word" : "break-all");
|
||||
putEvent('#button-preview' , 'click', this.activatePreview , this);
|
||||
putEvent('#button-reset' , 'click', this.reset , this);
|
||||
putEvent('#canvas-expand' , 'click', this.expand , this);
|
||||
putEvent('#canvas-crop' , 'click', this.crop , this);
|
||||
putEvent('[name="rotate"]' , 'change', e => this.setRotate(e.currentTarget.checked), this);
|
||||
this.#rotateCheck = document.querySelector('[name="rotate"]');
|
||||
|
||||
putEvent('[name="threshold"]', 'change', (event) => {
|
||||
this.threshold = parseInt(event.currentTarget.value);
|
||||
@ -374,17 +384,27 @@ class CanvasController {
|
||||
}, this);
|
||||
}
|
||||
useAlgorithm(name) {
|
||||
for (let e of this.algoElements) {
|
||||
e.checked = e.value === name;
|
||||
}
|
||||
this.algorithm = name;
|
||||
this.threshold = CanvasController.defaultThreshold;
|
||||
this._thresholdRange.dispatchEvent(new Event('change'));
|
||||
this.#thresholdRange.dispatchEvent(new Event('change'));
|
||||
this.energy = name == 'algo-direct' ? 96 : 64;
|
||||
this._energyRange.dispatchEvent(new Event('change'));
|
||||
this.#energyRange.dispatchEvent(new Event('change'));
|
||||
this.activatePreview();
|
||||
}
|
||||
expand(length = CanvasController.defaultHeight) {
|
||||
this.height += length;
|
||||
}
|
||||
crop() {}
|
||||
crop() {
|
||||
// STUB
|
||||
}
|
||||
setRotate(value) {
|
||||
this.#rotateCheck.checked = value;
|
||||
this.rotate = value;
|
||||
if (this.imageUrl !== null) this.putImage(this.imageUrl);
|
||||
}
|
||||
visualEnergy(amount) {
|
||||
let rate = amount / 256;
|
||||
let brightness = Math.max(1.6 - rate * 1.5, 0.75),
|
||||
@ -437,46 +457,68 @@ class CanvasController {
|
||||
this.previewData = mono_data;
|
||||
context_p.putImageData(new_data, 0, 0);
|
||||
}
|
||||
insertPicture(files) {
|
||||
const put_image = (url) => {
|
||||
this.imageUrl = url;
|
||||
let img = document.createElement('img');
|
||||
img.src = url;
|
||||
hidden_area.appendChild(img);
|
||||
img.addEventListener('load', () => {
|
||||
let canvas = this.canvas;
|
||||
let rate = img.height / img.width;
|
||||
this.height = canvas.width * rate;
|
||||
let context = canvas.getContext('2d');
|
||||
context.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||
this.crop();
|
||||
this.activatePreview();
|
||||
hint('#button-print');
|
||||
});
|
||||
}
|
||||
let use_files = (files) => {
|
||||
putImage(url) {
|
||||
let img = document.getElementById('img');
|
||||
img.src = url;
|
||||
img.addEventListener('load', () => {
|
||||
let canvas = this.canvas;
|
||||
let ctx = canvas.getContext('2d');
|
||||
if (this.rotate) {
|
||||
let intermediate_canvas = document.createElement('canvas');
|
||||
/**
|
||||
* w h
|
||||
* +------+ +---+
|
||||
* h | | | | w
|
||||
* +------+ | | intermediate_canvas
|
||||
* canvas +---+
|
||||
*/
|
||||
let w = canvas.width;
|
||||
let h = this.height = Math.floor(canvas.width * img.width / img.height);
|
||||
intermediate_canvas.width = h;
|
||||
intermediate_canvas.height = w;
|
||||
let i_ctx = intermediate_canvas.getContext('2d');
|
||||
i_ctx.drawImage(img, 0, 0, h, w);
|
||||
let i_data = i_ctx.getImageData(0, 0, h, w);
|
||||
let data = ctx.createImageData(w, h);
|
||||
for (let j = 0; j < h; j++) {
|
||||
for (let i = 0; i < w; i++) {
|
||||
for (let d = 0; d < 4; d++)
|
||||
data.data[(i * 4 + d) + (j * w * 4)] = i_data.data[(j * 4 + d) + ((w - i) * 4 * h)];
|
||||
}
|
||||
}
|
||||
ctx.putImageData(data, 0, 0);
|
||||
} else {
|
||||
this.height = Math.floor(canvas.width * img.height / img.width);
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
this.crop();
|
||||
this.activatePreview();
|
||||
hint('#button-print');
|
||||
});
|
||||
}
|
||||
useFiles(files) {
|
||||
const use_files = (files) => {
|
||||
let file = files[0];
|
||||
if (!file) return;
|
||||
let url = URL.createObjectURL(file);
|
||||
put_image(url);
|
||||
this.imageUrl = url;
|
||||
this.putImage(url);
|
||||
this.controls.classList.add('hidden');
|
||||
}
|
||||
if (files) use_files(files);
|
||||
else {
|
||||
document.querySelectorAll('.dummy').forEach(e => e.remove());
|
||||
let input = document.createElement('input');
|
||||
input.classList.add('dummy');
|
||||
input.type = 'file';
|
||||
input.accept = 'image/*';
|
||||
input.addEventListener('change', () => {
|
||||
use_files(input.files);
|
||||
});
|
||||
hidden_area.appendChild(input);
|
||||
input.click();
|
||||
}
|
||||
if (files) { use_files(files); return; }
|
||||
document.querySelectorAll('.dummy').forEach(e => e.remove());
|
||||
let input = document.createElement('input');
|
||||
input.classList.add('dummy');
|
||||
input.type = 'file';
|
||||
input.accept = 'image/*';
|
||||
input.addEventListener('change', () => {
|
||||
use_files(input.files);
|
||||
});
|
||||
hidden_area.appendChild(input);
|
||||
input.click();
|
||||
}
|
||||
insertText(text) {
|
||||
if (text == null || text.trim() == "") { return; }
|
||||
if (text == null || text.trim() == "") { return false; }
|
||||
|
||||
const text_size = parseInt(this.textSize.value);
|
||||
const text_font = this.textFont.value;
|
||||
@ -550,12 +592,12 @@ class CanvasController {
|
||||
|
||||
this.crop();
|
||||
|
||||
this.textAlgorithm.checked = true;
|
||||
this.textAlgorithm.dispatchEvent(new Event("change"));
|
||||
|
||||
this.imageUrl = this.canvas.toDataURL();
|
||||
this.activatePreview();
|
||||
|
||||
this.useAlgorithm('algo-direct');
|
||||
this.threshold = 16;
|
||||
|
||||
this.setRotate(false);
|
||||
this.putImage(this.imageUrl = this.canvas.toDataURL());
|
||||
|
||||
this.controls.classList.add('hidden');
|
||||
|
||||
hint('#button-print');
|
||||
@ -597,7 +639,7 @@ function applyI18nToDom(doc) {
|
||||
async function initI18n(current_language) {
|
||||
if (typeof i18n === 'undefined') return;
|
||||
/** @type {HTMLSelectElement} */
|
||||
let language_options = document.getElementById('select-language');
|
||||
let language_select = document.getElementById('select-language');
|
||||
/** @type {{ [code: string]: string }} */
|
||||
let list = await fetch('/lang/list.json').then(r => r.json());
|
||||
let use_language = async (value) => {
|
||||
@ -605,6 +647,7 @@ async function initI18n(current_language) {
|
||||
i18n.add(value, await fetch(`/lang/${value}.json`).then(r => r.json()), true);
|
||||
applyI18nToDom();
|
||||
}
|
||||
language_select.addEventListener('change', () => use_language(language_select.value));
|
||||
for (let code in list) {
|
||||
let option = document.createElement('option');
|
||||
option.value = code;
|
||||
@ -614,22 +657,22 @@ async function initI18n(current_language) {
|
||||
let option = event.currentTarget;
|
||||
let value = option.value;
|
||||
option.selected = true;
|
||||
language_options.selectedIndex = option.index;
|
||||
language_select.selectedIndex = option.index;
|
||||
use_language(value);
|
||||
Notice.note('welcome');
|
||||
});
|
||||
language_options.appendChild(option);
|
||||
language_select.appendChild(option);
|
||||
}
|
||||
if (!navigator.languages) {
|
||||
if (!navigator.language) return;
|
||||
else navigator.languages = [navigator.language, 'en-US'];
|
||||
}
|
||||
if (current_language) {
|
||||
for (let option of language_options.children)
|
||||
for (let option of language_select.children)
|
||||
if (option.value === current_language)
|
||||
option.click();
|
||||
} else for (let code of navigator.languages)
|
||||
if (list[code]) for (let option of language_options.children)
|
||||
if (list[code]) for (let option of language_select.children)
|
||||
if (option.value === code) {
|
||||
option.setAttribute('data-default', '');
|
||||
if (!current_language) option.click();
|
||||
@ -697,22 +740,22 @@ class Main {
|
||||
await initI18n(this.settings['language']);
|
||||
|
||||
this.canvasController = new CanvasController();
|
||||
putEvent('#button-exit', 'click', () => this.exit(false), this);
|
||||
putEvent('#button-exit', 'contextmenu',
|
||||
(event) => (event.preventDefault(), this.exit(true)), this);
|
||||
putEvent('#button-print', 'click', this.print, this);
|
||||
putEvent('#device-refresh', 'click', this.searchDevices, this);
|
||||
putEvent('#button-exit' , 'click', () => this.exit(false), this);
|
||||
putEvent('#button-print' , 'click', this.print, this);
|
||||
putEvent('#device-refresh' , 'click', this.searchDevices, this);
|
||||
putEvent('#button-exit' , 'contextmenu', (event) => (event.preventDefault(), this.exit(true)), this);
|
||||
putEvent('#set-accessibility', 'click', () => Dialog.alert('#accessibility'));
|
||||
this.attachSetter('#device-options', 'input', 'printer',
|
||||
(value) => callApi('/connect', { device: value })
|
||||
);
|
||||
putEvent('a[target="frame"]', 'click', () => Dialog.alert('#frame'));
|
||||
this.attachSetter('[name="scan-time"]', 'change', 'scan_timeout');
|
||||
this.attachSetter('input[name="algo"]', 'change', 'mono_algorithm',
|
||||
this.attachSetter('[name="scan-time"]' , 'change', 'scan_timeout');
|
||||
this.attachSetter('[name="rotate"]' , 'change', 'rotate');
|
||||
this.attachSetter('input[name="algo"]' , 'change', 'mono_algorithm',
|
||||
(value) => this.settings['text_mode'] = (value === 'algo-direct')
|
||||
);
|
||||
this.attachSetter('[name="transparent-as-white"]', 'change', 'transparent_as_white');
|
||||
this.attachSetter('[name="wrap-by-space"]', 'change', 'wrap_by_space');
|
||||
this.attachSetter('[name="wrap-words-by-spaces"]', 'change', 'wrap_by_space');
|
||||
this.attachSetter('[name="dry-run"]', 'change', 'dry_run',
|
||||
(checked) => checked && Notice.note('dry-run-test-print-process-only')
|
||||
);
|
||||
@ -731,16 +774,13 @@ class Main {
|
||||
this.attachSetter('[name="high-contrast"]', 'change', 'high_contrast',
|
||||
(checked) => apply_class('high-contrast', checked)
|
||||
);
|
||||
this.attachSetter('[name="threshold"]', 'change', 'threshold');
|
||||
this.attachSetter('[name="energy"]', 'change', 'energy');
|
||||
this.attachSetter('[name="quality"]', 'change', 'quality');
|
||||
this.attachSetter('[name="flip"]', 'change', 'flip');
|
||||
// this.attachSetter('[name="flip-h"]', 'change', 'flip_h');
|
||||
// this.attachSetter('[name="flip-v"]', 'change', 'flip_v');
|
||||
// this.attachSetter('[name="dump"]', 'change', 'dump');
|
||||
this.attachSetter('[name="threshold"]' , 'change', 'threshold');
|
||||
this.attachSetter('[name="energy"]' , 'change', 'energy');
|
||||
this.attachSetter('[name="quality"]' , 'change', 'quality');
|
||||
this.attachSetter('[name="flip"]' , 'change', 'flip');
|
||||
await this.activateConfig();
|
||||
// one exception
|
||||
this.attachSetter('#select-language option', 'click', 'language');
|
||||
this.attachSetter('#select-language', 'change', 'language');
|
||||
|
||||
if (this.settings['is_android']) {
|
||||
document.body.classList.add('android');
|
||||
@ -856,24 +896,29 @@ class Main {
|
||||
Notice.note('you-can-close-this-page-manually');
|
||||
}
|
||||
/** @param {Response} response */
|
||||
async bluetoothProblemHandler(response) {
|
||||
async handleBluetoothProblem(response) {
|
||||
// Not complete yet, it's different across other platforms
|
||||
let error_details = await response.json();
|
||||
if (
|
||||
error_details.name === 'org.bluez.Error.NotReady' ||
|
||||
error_details.name === 'org.freedesktop.DBus.Error.UnknownObject' ||
|
||||
error_details.name === 'org.bluez.Error.NotReady' ||
|
||||
error_details.details.includes('not turned on') ||
|
||||
error_details.details.includes('WinError -2147020577')
|
||||
) Notice.warn('please-enable-bluetooth');
|
||||
else if (
|
||||
error_details.details.includes('no running event loop')
|
||||
) Notice.error('internal-error-please-see-terminal');
|
||||
else throw new Error('Unknown Bluetooth Problem');
|
||||
else
|
||||
ErrorHandler.report(
|
||||
new Error('API Failure'),
|
||||
JSON.stringify(await response.json(), undefined, 4)
|
||||
)
|
||||
return null;
|
||||
}
|
||||
async searchDevices() {
|
||||
Notice.wait('scanning-for-devices');
|
||||
let search_result = await callApi('/devices', null, this.bluetoothProblemHandler);
|
||||
let search_result = await callApi('/devices', null, this.handleBluetoothProblem);
|
||||
if (search_result === null) return false;
|
||||
let devices = search_result.devices;
|
||||
Array.from(this.deviceOptions.children).forEach(e => e.remove());
|
||||
@ -901,23 +946,18 @@ class Main {
|
||||
method: 'POST',
|
||||
body: this.canvasController.makePbm()
|
||||
}).then(async (response) => {
|
||||
if (response.ok) Notice.note('finished')
|
||||
else {
|
||||
let json = response.json();
|
||||
response.json = () => json;
|
||||
let error_data = await response.json();
|
||||
if (/address.+not found|Not connected/.test(error_data.details) ||
|
||||
error_data.name === 'EOFError') {
|
||||
if (await this.searchDevices()) this.print();
|
||||
else Notice.error('please-check-if-the-printer-is-down');
|
||||
} else if (error_data.name === 'no-available-devices-found')
|
||||
Notice.warn('no-available-devices-found');
|
||||
else
|
||||
ErrorHandler.report(
|
||||
new Error('API Failure'),
|
||||
JSON.stringify(await response.json(), undefined, 4)
|
||||
)
|
||||
}
|
||||
if (response.ok) { Notice.note('finished'); return; }
|
||||
let json = response.json();
|
||||
response.json = () => json;
|
||||
let error_data = await response.json();
|
||||
if (/address.+not found|Not connected/.test(error_data.details) ||
|
||||
error_data.name === 'EOFError') {
|
||||
if (await this.searchDevices()) this.print();
|
||||
else Notice.error('please-check-if-the-printer-is-down');
|
||||
} else if (error_data.name === 'no-available-devices-found')
|
||||
Notice.warn('no-available-devices-found');
|
||||
else
|
||||
this.handleBluetoothProblem(response);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user