diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index d38162800..000000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -**/xtscancodes.js diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 10e15cec3..000000000 --- a/.eslintrc +++ /dev/null @@ -1,54 +0,0 @@ -{ - "env": { - "browser": true, - "es2020": true - }, - "parserOptions": { - "sourceType": "module", - "ecmaVersion": 2020 - }, - "extends": "eslint:recommended", - "rules": { - // Unsafe or confusing stuff that we forbid - - "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }], - "no-constant-condition": ["error", { "checkLoops": false }], - "no-var": "error", - "no-useless-constructor": "error", - "object-shorthand": ["error", "methods", { "avoidQuotes": true }], - "prefer-arrow-callback": "error", - "arrow-body-style": ["error", "as-needed", { "requireReturnForObjectLiteral": false } ], - "arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }], - "arrow-spacing": ["error"], - "no-confusing-arrow": ["error", { "allowParens": true }], - - // Enforced coding style - - "brace-style": ["error", "1tbs", { "allowSingleLine": true }], - "indent": ["error", 4, { "SwitchCase": 1, - "VariableDeclarator": "first", - "FunctionDeclaration": { "parameters": "first" }, - "FunctionExpression": { "parameters": "first" }, - "CallExpression": { "arguments": "first" }, - "ArrayExpression": "first", - "ObjectExpression": "first", - "ImportDeclaration": "first", - "ignoreComments": true }], - "comma-spacing": ["error"], - "comma-style": ["error"], - "curly": ["error", "multi-line"], - "func-call-spacing": ["error"], - "func-names": ["error"], - "func-style": ["error", "declaration", { "allowArrowFunctions": true }], - "key-spacing": ["error"], - "keyword-spacing": ["error"], - "no-trailing-spaces": ["error"], - "semi": ["error"], - "space-before-blocks": ["error"], - "space-before-function-paren": ["error", { "anonymous": "always", - "named": "never", - "asyncArrow": "always" }], - "switch-colon-spacing": ["error"], - "camelcase": ["error", { allow: ["^XK_", "^XF86XK_"] }], - } -} diff --git a/README.md b/README.md index a771cb438..b95d15e65 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,6 @@ for a more complete list with additional info and links. ### News/help/contact The project website is found at [novnc.com](http://novnc.com). -Notable commits, announcements and news are posted to -[@noVNC](http://www.twitter.com/noVNC). If you are a noVNC developer/integrator/user (or want to be) please join the [noVNC discussion group](https://groups.google.com/forum/?fromgroups#!forum/novnc). @@ -59,7 +57,6 @@ profits such as: [Electronic Frontier Foundation](https://www.eff.org/), [Against Malaria Foundation](http://www.againstmalaria.com/), [Nothing But Nets](http://www.nothingbutnets.net/), etc. -Please tweet [@noVNC](http://www.twitter.com/noVNC) if you do. ### Features diff --git a/app/locale/el.json b/app/locale/el.json index f801251c5..4df3e03c4 100644 --- a/app/locale/el.json +++ b/app/locale/el.json @@ -1,4 +1,5 @@ { + "HTTPS is required for full functionality": "Το HTTPS είναι απαιτούμενο για πλήρη λειτουργικότητα", "Connecting...": "Συνδέεται...", "Disconnecting...": "Aποσυνδέεται...", "Reconnecting...": "Επανασυνδέεται...", @@ -7,19 +8,15 @@ "Connected (encrypted) to ": "Συνδέθηκε (κρυπτογραφημένα) με το ", "Connected (unencrypted) to ": "Συνδέθηκε (μη κρυπτογραφημένα) με το ", "Something went wrong, connection is closed": "Κάτι πήγε στραβά, η σύνδεση διακόπηκε", + "Failed to connect to server": "Αποτυχία στη σύνδεση με το διακομιστή", "Disconnected": "Αποσυνδέθηκε", "New connection has been rejected with reason: ": "Η νέα σύνδεση απορρίφθηκε διότι: ", "New connection has been rejected": "Η νέα σύνδεση απορρίφθηκε ", - "Password is required": "Απαιτείται ο κωδικός πρόσβασης", + "Credentials are required": "Απαιτούνται διαπιστευτήρια", "noVNC encountered an error:": "το noVNC αντιμετώπισε ένα σφάλμα:", "Hide/Show the control bar": "Απόκρυψη/Εμφάνιση γραμμής ελέγχου", + "Drag": "Σύρσιμο", "Move/Drag Viewport": "Μετακίνηση/Σύρσιμο Θεατού πεδίου", - "viewport drag": "σύρσιμο θεατού πεδίου", - "Active Mouse Button": "Ενεργό Πλήκτρο Ποντικιού", - "No mousebutton": "Χωρίς Πλήκτρο Ποντικιού", - "Left mousebutton": "Αριστερό Πλήκτρο Ποντικιού", - "Middle mousebutton": "Μεσαίο Πλήκτρο Ποντικιού", - "Right mousebutton": "Δεξί Πλήκτρο Ποντικιού", "Keyboard": "Πληκτρολόγιο", "Show Keyboard": "Εμφάνιση Πληκτρολογίου", "Extra keys": "Επιπλέον πλήκτρα", @@ -28,6 +25,8 @@ "Toggle Ctrl": "Εναλλαγή Ctrl", "Alt": "Alt", "Toggle Alt": "Εναλλαγή Alt", + "Toggle Windows": "Εναλλαγή Παράθυρων", + "Windows": "Παράθυρα", "Send Tab": "Αποστολή Tab", "Tab": "Tab", "Esc": "Esc", @@ -41,8 +40,7 @@ "Reboot": "Επανεκκίνηση", "Reset": "Επαναφορά", "Clipboard": "Πρόχειρο", - "Clear": "Καθάρισμα", - "Fullscreen": "Πλήρης Οθόνη", + "Edit clipboard content in the textarea below.": "Επεξεργαστείτε το περιεχόμενο του πρόχειρου στην περιοχή κειμένου παρακάτω.", "Settings": "Ρυθμίσεις", "Shared Mode": "Κοινόχρηστη Λειτουργία", "View Only": "Μόνο Θέαση", @@ -52,6 +50,8 @@ "Local Scaling": "Τοπική Κλιμάκωση", "Remote Resizing": "Απομακρυσμένη Αλλαγή μεγέθους", "Advanced": "Για προχωρημένους", + "Quality:": "Ποιότητα:", + "Compression level:": "Επίπεδο συμπίεσης:", "Repeater ID:": "Repeater ID:", "WebSocket": "WebSocket", "Encrypt": "Κρυπτογράφηση", @@ -60,10 +60,20 @@ "Path:": "Διαδρομή:", "Automatic Reconnect": "Αυτόματη επανασύνδεση", "Reconnect Delay (ms):": "Καθυστέρηση επανασύνδεσης (ms):", + "Show Dot when No Cursor": "Εμφάνιση Τελείας όταν δεν υπάρχει Δρομέας", "Logging:": "Καταγραφή:", + "Version:": "Έκδοση:", "Disconnect": "Αποσύνδεση", "Connect": "Σύνδεση", + "Server identity": "Ταυτότητα Διακομιστή", + "The server has provided the following identifying information:": "Ο διακομιστής παρείχε την ακόλουθη πληροφορία ταυτοποίησης:", + "Fingerprint:": "Δακτυλικό αποτύπωμα:", + "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "Παρακαλώ επαληθεύσετε ότι η πληροφορία είναι σωστή και πιέστε \"Αποδοχή\". Αλλιώς πιέστε \"Απόρριψη\".", + "Approve": "Αποδοχή", + "Reject": "Απόρριψη", + "Credentials": "Διαπιστευτήρια", + "Username:": "Κωδικός Χρήστη:", "Password:": "Κωδικός Πρόσβασης:", - "Cancel": "Ακύρωση", - "Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas" + "Send Credentials": "Αποστολή Διαπιστευτηρίων", + "Cancel": "Ακύρωση" } \ No newline at end of file diff --git a/app/locale/fr.json b/app/locale/fr.json index 22531f73b..c0eeec7d3 100644 --- a/app/locale/fr.json +++ b/app/locale/fr.json @@ -1,5 +1,4 @@ { - "HTTPS is required for full functionality": "", "Connecting...": "En cours de connexion...", "Disconnecting...": "Déconnexion en cours...", "Reconnecting...": "Reconnexion en cours...", @@ -40,7 +39,8 @@ "Reboot": "Redémarrer", "Reset": "Réinitialiser", "Clipboard": "Presse-papiers", - "Edit clipboard content in the textarea below.": "", + "Clear": "Effacer", + "Fullscreen": "Plein écran", "Settings": "Paramètres", "Shared Mode": "Mode partagé", "View Only": "Afficher uniquement", @@ -65,12 +65,6 @@ "Version:": "Version :", "Disconnect": "Déconnecter", "Connect": "Connecter", - "Server identity": "", - "The server has provided the following identifying information:": "", - "Fingerprint:": "", - "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "", - "Approve": "", - "Reject": "", "Username:": "Nom d'utilisateur :", "Password:": "Mot de passe :", "Send Credentials": "Envoyer les identifiants", diff --git a/app/locale/it.json b/app/locale/it.json index 6fd25702b..18a7f7447 100644 --- a/app/locale/it.json +++ b/app/locale/it.json @@ -14,8 +14,6 @@ "Credentials are required": "Le credenziali sono obbligatorie", "noVNC encountered an error:": "noVNC ha riscontrato un errore:", "Hide/Show the control bar": "Nascondi/Mostra la barra di controllo", - "Drag": "", - "Move/Drag Viewport": "", "Keyboard": "Tastiera", "Show Keyboard": "Mostra tastiera", "Extra keys": "Tasti Aggiuntivi", @@ -44,7 +42,6 @@ "Settings": "Impostazioni", "Shared Mode": "Modalità condivisa", "View Only": "Sola Visualizzazione", - "Clip to Window": "", "Scaling Mode:": "Modalità di ridimensionamento:", "None": "Nessuna", "Local Scaling": "Ridimensionamento Locale", @@ -61,7 +58,6 @@ "Automatic Reconnect": "Riconnessione Automatica", "Reconnect Delay (ms):": "Ritardo Riconnessione (ms):", "Show Dot when No Cursor": "Mostra Punto quando Nessun Cursore", - "Logging:": "", "Version:": "Versione:", "Disconnect": "Disconnetti", "Connect": "Connetti", diff --git a/app/locale/ja.json b/app/locale/ja.json index 43fc5bf38..70fd7a5d1 100644 --- a/app/locale/ja.json +++ b/app/locale/ja.json @@ -1,4 +1,5 @@ { + "HTTPS is required for full functionality": "すべての機能を使用するにはHTTPS接続が必要です", "Connecting...": "接続しています...", "Disconnecting...": "切断しています...", "Reconnecting...": "再接続しています...", @@ -21,10 +22,10 @@ "Extra keys": "追加キー", "Show Extra Keys": "追加キーを表示", "Ctrl": "Ctrl", - "Toggle Ctrl": "Ctrl キーを切り替え", + "Toggle Ctrl": "Ctrl キーをトグル", "Alt": "Alt", - "Toggle Alt": "Alt キーを切り替え", - "Toggle Windows": "Windows キーを切り替え", + "Toggle Alt": "Alt キーをトグル", + "Toggle Windows": "Windows キーをトグル", "Windows": "Windows", "Send Tab": "Tab キーを送信", "Tab": "Tab", @@ -39,11 +40,11 @@ "Reboot": "再起動", "Reset": "リセット", "Clipboard": "クリップボード", - "Clear": "クリア", - "Fullscreen": "全画面表示", + "Edit clipboard content in the textarea below.": "以下の入力欄からクリップボードの内容を編集できます。", + "Full Screen": "全画面表示", "Settings": "設定", "Shared Mode": "共有モード", - "View Only": "表示のみ", + "View Only": "表示専用", "Clip to Window": "ウィンドウにクリップ", "Scaling Mode:": "スケーリングモード:", "None": "なし", @@ -60,11 +61,18 @@ "Path:": "パス:", "Automatic Reconnect": "自動再接続", "Reconnect Delay (ms):": "再接続する遅延 (ミリ秒):", - "Show Dot when No Cursor": "カーソルがないときにドットを表示", + "Show Dot when No Cursor": "カーソルがないときにドットを表示する", "Logging:": "ロギング:", "Version:": "バージョン:", "Disconnect": "切断", "Connect": "接続", + "Server identity": "サーバーの識別情報", + "The server has provided the following identifying information:": "サーバーは以下の識別情報を提供しています:", + "Fingerprint:": "フィンガープリント:", + "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "この情報が正しい場合は「承認」を、そうでない場合は「拒否」を押してください。", + "Approve": "承認", + "Reject": "拒否", + "Credentials": "資格情報", "Username:": "ユーザー名:", "Password:": "パスワード:", "Send Credentials": "資格情報を送信", diff --git a/app/locale/sv.json b/app/locale/sv.json index 077ef42c8..80a400bfa 100644 --- a/app/locale/sv.json +++ b/app/locale/sv.json @@ -1,10 +1,11 @@ { - "HTTPS is required for full functionality": "HTTPS krävs för full funktionalitet", + "Running without HTTPS is not recommended, crashes or other issues are likely.": "Det är ej rekommenderat att köra utan HTTPS, krascher och andra problem är troliga.", "Connecting...": "Ansluter...", "Disconnecting...": "Kopplar ner...", "Reconnecting...": "Återansluter...", "Internal error": "Internt fel", "Must set host": "Du måste specifiera en värd", + "Failed to connect to server: ": "Misslyckades att ansluta till servern: ", "Connected (encrypted) to ": "Ansluten (krypterat) till ", "Connected (unencrypted) to ": "Ansluten (okrypterat) till ", "Something went wrong, connection is closed": "Något gick fel, anslutningen avslutades", diff --git a/app/locale/zh_CN.json b/app/locale/zh_CN.json index 70c01161e..4c87e9805 100644 --- a/app/locale/zh_CN.json +++ b/app/locale/zh_CN.json @@ -1,70 +1,70 @@ { "Connecting...": "连接中...", + "Connected (encrypted) to ": "已连接(已加密)到", + "Connected (unencrypted) to ": "已连接(未加密)到", "Disconnecting...": "正在断开连接...", - "Reconnecting...": "重新连接中...", - "Internal error": "内部错误", - "Must set host": "请提供主机名", - "Connected (encrypted) to ": "已连接到(加密)", - "Connected (unencrypted) to ": "已连接到(未加密)", - "Something went wrong, connection is closed": "发生错误,连接已关闭", - "Failed to connect to server": "无法连接到服务器", "Disconnected": "已断开连接", - "New connection has been rejected with reason: ": "连接被拒绝,原因:", - "New connection has been rejected": "连接被拒绝", + "Must set host": "必须设置主机", + "Reconnecting...": "重新连接中...", "Password is required": "请提供密码", + "Disconnect timeout": "超时断开", "noVNC encountered an error:": "noVNC 遇到一个错误:", "Hide/Show the control bar": "显示/隐藏控制栏", - "Move/Drag Viewport": "拖放显示范围", - "viewport drag": "显示范围拖放", - "Active Mouse Button": "启动鼠标按鍵", - "No mousebutton": "禁用鼠标按鍵", - "Left mousebutton": "鼠标左鍵", - "Middle mousebutton": "鼠标中鍵", - "Right mousebutton": "鼠标右鍵", + "Move/Drag Viewport": "移动/拖动窗口", + "viewport drag": "窗口拖动", + "Active Mouse Button": "启动鼠标按键", + "No mousebutton": "禁用鼠标按键", + "Left mousebutton": "鼠标左键", + "Middle mousebutton": "鼠标中键", + "Right mousebutton": "鼠标右键", "Keyboard": "键盘", "Show Keyboard": "显示键盘", "Extra keys": "额外按键", "Show Extra Keys": "显示额外按键", "Ctrl": "Ctrl", "Toggle Ctrl": "切换 Ctrl", + "Edit clipboard content in the textarea below.": "在下面的文本区域中编辑剪贴板内容。", "Alt": "Alt", "Toggle Alt": "切换 Alt", "Send Tab": "发送 Tab 键", "Tab": "Tab", "Esc": "Esc", "Send Escape": "发送 Escape 键", - "Ctrl+Alt+Del": "Ctrl-Alt-Del", - "Send Ctrl-Alt-Del": "发送 Ctrl-Alt-Del 键", - "Shutdown/Reboot": "关机/重新启动", - "Shutdown/Reboot...": "关机/重新启动...", + "Ctrl+Alt+Del": "Ctrl+Alt+Del", + "Send Ctrl-Alt-Del": "发送 Ctrl+Alt+Del 键", + "Shutdown/Reboot": "关机/重启", + "Shutdown/Reboot...": "关机/重启...", "Power": "电源", "Shutdown": "关机", - "Reboot": "重新启动", + "Reboot": "重启", "Reset": "重置", "Clipboard": "剪贴板", "Clear": "清除", "Fullscreen": "全屏", "Settings": "设置", + "Encrypt": "加密", "Shared Mode": "分享模式", "View Only": "仅查看", "Clip to Window": "限制/裁切窗口大小", "Scaling Mode:": "缩放模式:", "None": "无", "Local Scaling": "本地缩放", + "Local Downscaling": "降低本地尺寸", "Remote Resizing": "远程调整大小", "Resizing browser": "调整浏览器大小", "Advanced": "高级", + "Local Cursor": "本地光标", "Repeater ID:": "中继站 ID", "WebSocket": "WebSocket", - "Encrypt": "加密", "Host:": "主机:", "Port:": "端口:", "Path:": "路径:", "Automatic Reconnect": "自动重新连接", "Reconnect Delay (ms):": "重新连接间隔 (ms):", "Logging:": "日志级别:", - "Disconnect": "中断连接", + "Disconnect": "断开连接", "Connect": "连接", "Password:": "密码:", - "Cancel": "取消" + "Cancel": "取消", + "Canvas not supported.": "不支持 Canvas。" } \ No newline at end of file diff --git a/app/ui.js b/app/ui.js index 86ebdeed0..062d7d2f6 100644 --- a/app/ui.js +++ b/app/ui.js @@ -158,20 +158,7 @@ const UI = { UI.initSetting('logging', 'warn'); UI.updateLogging(); - // if port == 80 (or 443) then it won't be present and should be - // set manually - let port = window.location.port; - if (!port) { - if (window.location.protocol.substring(0, 5) == 'https') { - port = 443; - } else if (window.location.protocol.substring(0, 4) == 'http') { - port = 80; - } - } - /* Populate the controls if defaults are provided in the URL */ - UI.initSetting('host', window.location.hostname); - UI.initSetting('port', port); UI.initSetting('encrypt', (window.location.protocol === "https:")); UI.initSetting('view_clip', false); UI.initSetting('resize', 'off'); @@ -1021,28 +1008,31 @@ const UI = { UI.hideStatus(); - if (!host) { - Log.Error("Can't connect when host is: " + host); - UI.showStatus(_("Must set host"), 'error'); - return; - } - UI.closeConnectPanel(); UI.updateVisualState('connecting'); let url; - url = UI.getSetting('encrypt') ? 'wss' : 'ws'; + if (host) { + url = new URL("https://" + host); - url += '://' + host; - if (port) { - url += ':' + port; + url.protocol = UI.getSetting('encrypt') ? 'wss:' : 'ws:'; + if (port) { + url.port = port; + } + url.pathname = '/' + path; + } else { + // Current (May 2024) browsers support relative WebSocket + // URLs natively, but we need to support older browsers for + // some time. + url = new URL(path, location.href); + url.protocol = (window.location.protocol === "https:") ? 'wss:' : 'ws:'; } - url += '/' + path; try { - UI.rfb = new RFB(document.getElementById('noVNC_container'), url, + UI.rfb = new RFB(document.getElementById('noVNC_container'), + url.href, { shared: UI.getSetting('shared'), repeaterID: UI.getSetting('repeaterID'), credentials: { password: password } }); diff --git a/core/decoders/tight.js b/core/decoders/tight.js index 45622080f..8bc977a79 100644 --- a/core/decoders/tight.js +++ b/core/decoders/tight.js @@ -285,7 +285,73 @@ export default class TightDecoder { } _gradientFilter(streamId, x, y, width, height, sock, display, depth) { - throw new Error("Gradient filter not implemented"); + // assume the TPIXEL is 3 bytes long + const uncompressedSize = width * height * 3; + let data; + + if (uncompressedSize === 0) { + return true; + } + + if (uncompressedSize < 12) { + if (sock.rQwait("TIGHT", uncompressedSize)) { + return false; + } + + data = sock.rQshiftBytes(uncompressedSize); + } else { + data = this._readData(sock); + if (data === null) { + return false; + } + + this._zlibs[streamId].setInput(data); + data = this._zlibs[streamId].inflate(uncompressedSize); + this._zlibs[streamId].setInput(null); + } + + let rgbx = new Uint8Array(4 * width * height); + + let rgbxIndex = 0, dataIndex = 0; + let left = new Uint8Array(3); + for (let x = 0; x < width; x++) { + for (let c = 0; c < 3; c++) { + const prediction = left[c]; + const value = data[dataIndex++] + prediction; + rgbx[rgbxIndex++] = value; + left[c] = value; + } + rgbx[rgbxIndex++] = 255; + } + + let upperIndex = 0; + let upper = new Uint8Array(3), + upperleft = new Uint8Array(3); + for (let y = 1; y < height; y++) { + left.fill(0); + upperleft.fill(0); + for (let x = 0; x < width; x++) { + for (let c = 0; c < 3; c++) { + upper[c] = rgbx[upperIndex++]; + let prediction = left[c] + upper[c] - upperleft[c]; + if (prediction < 0) { + prediction = 0; + } else if (prediction > 255) { + prediction = 255; + } + const value = data[dataIndex++] + prediction; + rgbx[rgbxIndex++] = value; + upperleft[c] = upper[c]; + left[c] = value; + } + rgbx[rgbxIndex++] = 255; + upperIndex++; + } + } + + display.blitImage(x, y, width, height, rgbx, 0, false); + + return true; } _readData(sock) { diff --git a/core/input/keyboard.js b/core/input/keyboard.js index 68da2312b..ff14de849 100644 --- a/core/input/keyboard.js +++ b/core/input/keyboard.js @@ -203,7 +203,7 @@ export default class Keyboard { if ((code === "ControlLeft") && browser.isWindows() && !("ControlLeft" in this._keyDownList)) { this._altGrArmed = true; - this._altGrTimeout = setTimeout(this._handleAltGrTimeout.bind(this), 100); + this._altGrTimeout = setTimeout(this._interruptAltGrSequence.bind(this), 100); this._altGrCtrlTime = e.timeStamp; return; } @@ -218,11 +218,7 @@ export default class Keyboard { // We can't get a release in the middle of an AltGr sequence, so // abort that detection - if (this._altGrArmed) { - this._altGrArmed = false; - clearTimeout(this._altGrTimeout); - this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true); - } + this._interruptAltGrSequence(); // See comment in _handleKeyDown() if ((browser.isMac() || browser.isIOS()) && (code === 'CapsLock')) { @@ -249,14 +245,20 @@ export default class Keyboard { } } - _handleAltGrTimeout() { - this._altGrArmed = false; - clearTimeout(this._altGrTimeout); - this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true); + _interruptAltGrSequence() { + if (this._altGrArmed) { + this._altGrArmed = false; + clearTimeout(this._altGrTimeout); + this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true); + } } _allKeysUp() { Log.Debug(">> Keyboard.allKeysUp"); + + // Prevent control key being processed after losing focus. + this._interruptAltGrSequence(); + for (let code in this._keyDownList) { this._sendKeyEvent(this._keyDownList[code], code, false); } diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..13b1a32a4 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,102 @@ +import globals from "globals"; +import js from "@eslint/js"; + +export default [ + js.configs.recommended, + { + languageOptions: { + ecmaVersion: 2020, + sourceType: "module", + globals: { + ...globals.browser, + ...globals.es2020, + } + }, + ignores: ["**/xtscancodes.js"], + rules: { + // Unsafe or confusing stuff that we forbid + + "no-unused-vars": ["error", { "vars": "all", + "args": "none", + "ignoreRestSiblings": true, + "caughtErrors": "none" }], + "no-constant-condition": ["error", { "checkLoops": false }], + "no-var": "error", + "no-useless-constructor": "error", + "object-shorthand": ["error", "methods", { "avoidQuotes": true }], + "prefer-arrow-callback": "error", + "arrow-body-style": ["error", "as-needed", { "requireReturnForObjectLiteral": false } ], + "arrow-parens": ["error", "as-needed", { "requireForBlockBody": true }], + "arrow-spacing": ["error"], + "no-confusing-arrow": ["error", { "allowParens": true }], + + // Enforced coding style + + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "indent": ["error", 4, { "SwitchCase": 1, + "VariableDeclarator": "first", + "FunctionDeclaration": { "parameters": "first" }, + "FunctionExpression": { "parameters": "first" }, + "CallExpression": { "arguments": "first" }, + "ArrayExpression": "first", + "ObjectExpression": "first", + "ImportDeclaration": "first", + "ignoreComments": true }], + "comma-spacing": ["error"], + "comma-style": ["error"], + "curly": ["error", "multi-line"], + "func-call-spacing": ["error"], + "func-names": ["error"], + "func-style": ["error", "declaration", { "allowArrowFunctions": true }], + "key-spacing": ["error"], + "keyword-spacing": ["error"], + "no-trailing-spaces": ["error"], + "semi": ["error"], + "space-before-blocks": ["error"], + "space-before-function-paren": ["error", { "anonymous": "always", + "named": "never", + "asyncArrow": "always" }], + "switch-colon-spacing": ["error"], + "camelcase": ["error", { "allow": ["^XK_", "^XF86XK_"] }], + "no-console": ["error"], + } + }, + { + files: ["po/po2js", "po/xgettext-html"], + languageOptions: { + globals: { + ...globals.node, + } + }, + rules: { + "no-console": 0, + }, + }, + { + files: ["tests/*"], + languageOptions: { + globals: { + ...globals.node, + ...globals.mocha, + sinon: false, + expect: false, + } + }, + rules: { + "prefer-arrow-callback": 0, + // Too many anonymous callbacks + "func-names": "off", + }, + }, + { + files: ["utils/*"], + languageOptions: { + globals: { + ...globals.node, + } + }, + rules: { + "no-console": 0, + }, + }, +]; diff --git a/karma.conf.js b/karma.conf.js index faa8beea2..54380ebd2 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -27,15 +27,22 @@ module.exports = (config) => { // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['mocha', 'sinon-chai'], + frameworks: ['mocha'], - // list of files / patterns to load in the browser (loaded in order) + // list of files / patterns to load in the browser files: [ + // node modules + { pattern: 'node_modules/chai/**', included: false }, + { pattern: 'node_modules/sinon/**', included: false }, + { pattern: 'node_modules/sinon-chai/**', included: false }, + // modules to test { pattern: 'app/localization.js', included: false, type: 'module' }, { pattern: 'app/webutil.js', included: false, type: 'module' }, { pattern: 'core/**/*.js', included: false, type: 'module' }, { pattern: 'vendor/pako/**/*.js', included: false, type: 'module' }, + // tests { pattern: 'tests/test.*.js', type: 'module' }, + // test support files { pattern: 'tests/fake.*.js', included: false, type: 'module' }, { pattern: 'tests/assertions.js', type: 'module' }, ], @@ -81,12 +88,5 @@ module.exports = (config) => { singleRun: true, }; - if (process.env.TEST_BROWSER_NAME === 'ChromeHeadless') { - let os = require('os'); - if (os.platform() === 'win32') { - my_conf.client.mocha['timeout'] = 5000; - } - } - config.set(my_conf); }; diff --git a/package.json b/package.json index 482b86eb3..e28850a8d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@novnc/novnc", - "version": "1.4.0", + "version": "1.5.0", "description": "An HTML5 VNC client", "browser": "lib/rfb", "directories": { @@ -44,6 +44,7 @@ "commander": "latest", "eslint": "latest", "fs-extra": "latest", + "globals": "latest", "jsdom": "latest", "karma": "latest", "karma-mocha": "latest", @@ -54,7 +55,6 @@ "karma-mocha-reporter": "latest", "karma-safari-launcher": "latest", "karma-script-launcher": "latest", - "karma-sinon-chai": "latest", "mocha": "latest", "node-getopt": "latest", "po2json": "latest", diff --git a/po/.eslintrc b/po/.eslintrc deleted file mode 100644 index a0157e2a8..000000000 --- a/po/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "env": { - "node": true, - }, -} diff --git a/po/el.po b/po/el.po index 5213ae542..de690fe93 100644 --- a/po/el.po +++ b/po/el.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: noVNC 0.6.1\n" "Report-Msgid-Bugs-To: novnc@googlegroups.com\n" -"POT-Creation-Date: 2017-11-17 21:40+0200\n" +"POT-Creation-Date: 2022-12-27 15:24+0100\n" "PO-Revision-Date: 2017-10-11 16:16+0200\n" "Last-Translator: Giannis Kosmas \n" "Language-Team: none\n" @@ -17,273 +17,349 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../app/ui.js:404 +#: ../app/ui.js:69 +msgid "HTTPS is required for full functionality" +msgstr "Το HTTPS είναι απαιτούμενο για πλήρη λειτουργικότητα" + +#: ../app/ui.js:410 msgid "Connecting..." msgstr "Συνδέεται..." -#: ../app/ui.js:411 +#: ../app/ui.js:417 msgid "Disconnecting..." msgstr "Aποσυνδέεται..." -#: ../app/ui.js:417 +#: ../app/ui.js:423 msgid "Reconnecting..." msgstr "Επανασυνδέεται..." -#: ../app/ui.js:422 +#: ../app/ui.js:428 msgid "Internal error" msgstr "Εσωτερικό σφάλμα" -#: ../app/ui.js:1019 +#: ../app/ui.js:1026 msgid "Must set host" msgstr "Πρέπει να οριστεί ο διακομιστής" -#: ../app/ui.js:1099 +#: ../app/ui.js:1110 msgid "Connected (encrypted) to " msgstr "Συνδέθηκε (κρυπτογραφημένα) με το " -#: ../app/ui.js:1101 +#: ../app/ui.js:1112 msgid "Connected (unencrypted) to " msgstr "Συνδέθηκε (μη κρυπτογραφημένα) με το " -#: ../app/ui.js:1119 +#: ../app/ui.js:1135 msgid "Something went wrong, connection is closed" msgstr "Κάτι πήγε στραβά, η σύνδεση διακόπηκε" -#: ../app/ui.js:1129 +#: ../app/ui.js:1138 +msgid "Failed to connect to server" +msgstr "Αποτυχία στη σύνδεση με το διακομιστή" + +#: ../app/ui.js:1150 msgid "Disconnected" msgstr "Αποσυνδέθηκε" -#: ../app/ui.js:1142 +#: ../app/ui.js:1165 msgid "New connection has been rejected with reason: " msgstr "Η νέα σύνδεση απορρίφθηκε διότι: " -#: ../app/ui.js:1145 +#: ../app/ui.js:1168 msgid "New connection has been rejected" msgstr "Η νέα σύνδεση απορρίφθηκε " -#: ../app/ui.js:1166 -msgid "Password is required" -msgstr "Απαιτείται ο κωδικός πρόσβασης" +#: ../app/ui.js:1234 +msgid "Credentials are required" +msgstr "Απαιτούνται διαπιστευτήρια" -#: ../vnc.html:89 +#: ../vnc.html:57 msgid "noVNC encountered an error:" msgstr "το noVNC αντιμετώπισε ένα σφάλμα:" -#: ../vnc.html:99 +#: ../vnc.html:67 msgid "Hide/Show the control bar" msgstr "Απόκρυψη/Εμφάνιση γραμμής ελέγχου" -#: ../vnc.html:106 +#: ../vnc.html:76 +msgid "Drag" +msgstr "Σύρσιμο" + +#: ../vnc.html:76 msgid "Move/Drag Viewport" msgstr "Μετακίνηση/Σύρσιμο Θεατού πεδίου" -#: ../vnc.html:106 -msgid "viewport drag" -msgstr "σύρσιμο θεατού πεδίου" - -#: ../vnc.html:112 ../vnc.html:115 ../vnc.html:118 ../vnc.html:121 -msgid "Active Mouse Button" -msgstr "Ενεργό Πλήκτρο Ποντικιού" - -#: ../vnc.html:112 -msgid "No mousebutton" -msgstr "Χωρίς Πλήκτρο Ποντικιού" - -#: ../vnc.html:115 -msgid "Left mousebutton" -msgstr "Αριστερό Πλήκτρο Ποντικιού" - -#: ../vnc.html:118 -msgid "Middle mousebutton" -msgstr "Μεσαίο Πλήκτρο Ποντικιού" - -#: ../vnc.html:121 -msgid "Right mousebutton" -msgstr "Δεξί Πλήκτρο Ποντικιού" - -#: ../vnc.html:124 +#: ../vnc.html:82 msgid "Keyboard" msgstr "Πληκτρολόγιο" -#: ../vnc.html:124 +#: ../vnc.html:82 msgid "Show Keyboard" msgstr "Εμφάνιση Πληκτρολογίου" -#: ../vnc.html:131 +#: ../vnc.html:87 msgid "Extra keys" msgstr "Επιπλέον πλήκτρα" -#: ../vnc.html:131 +#: ../vnc.html:87 msgid "Show Extra Keys" msgstr "Εμφάνιση Επιπλέον Πλήκτρων" -#: ../vnc.html:136 +#: ../vnc.html:92 msgid "Ctrl" msgstr "Ctrl" -#: ../vnc.html:136 +#: ../vnc.html:92 msgid "Toggle Ctrl" msgstr "Εναλλαγή Ctrl" -#: ../vnc.html:139 +#: ../vnc.html:95 msgid "Alt" msgstr "Alt" -#: ../vnc.html:139 +#: ../vnc.html:95 msgid "Toggle Alt" msgstr "Εναλλαγή Alt" -#: ../vnc.html:142 +#: ../vnc.html:98 +msgid "Toggle Windows" +msgstr "Εναλλαγή Παράθυρων" + +#: ../vnc.html:98 +msgid "Windows" +msgstr "Παράθυρα" + +#: ../vnc.html:101 msgid "Send Tab" msgstr "Αποστολή Tab" -#: ../vnc.html:142 +#: ../vnc.html:101 msgid "Tab" msgstr "Tab" -#: ../vnc.html:145 +#: ../vnc.html:104 msgid "Esc" msgstr "Esc" -#: ../vnc.html:145 +#: ../vnc.html:104 msgid "Send Escape" msgstr "Αποστολή Escape" -#: ../vnc.html:148 +#: ../vnc.html:107 msgid "Ctrl+Alt+Del" msgstr "Ctrl+Alt+Del" -#: ../vnc.html:148 +#: ../vnc.html:107 msgid "Send Ctrl-Alt-Del" msgstr "Αποστολή Ctrl-Alt-Del" -#: ../vnc.html:156 +#: ../vnc.html:114 msgid "Shutdown/Reboot" msgstr "Κλείσιμο/Επανεκκίνηση" -#: ../vnc.html:156 +#: ../vnc.html:114 msgid "Shutdown/Reboot..." msgstr "Κλείσιμο/Επανεκκίνηση..." -#: ../vnc.html:162 +#: ../vnc.html:120 msgid "Power" msgstr "Απενεργοποίηση" -#: ../vnc.html:164 +#: ../vnc.html:122 msgid "Shutdown" msgstr "Κλείσιμο" -#: ../vnc.html:165 +#: ../vnc.html:123 msgid "Reboot" msgstr "Επανεκκίνηση" -#: ../vnc.html:166 +#: ../vnc.html:124 msgid "Reset" msgstr "Επαναφορά" -#: ../vnc.html:171 ../vnc.html:177 +#: ../vnc.html:129 ../vnc.html:135 msgid "Clipboard" msgstr "Πρόχειρο" -#: ../vnc.html:181 -msgid "Clear" -msgstr "Καθάρισμα" +#: ../vnc.html:137 +msgid "Edit clipboard content in the textarea below." +msgstr "Επεξεργαστείτε το περιεχόμενο του πρόχειρου στην περιοχή κειμένου παρακάτω." -#: ../vnc.html:187 -msgid "Fullscreen" +#: ../vnc.html:145 +#, fuzzy +msgid "Full Screen" msgstr "Πλήρης Οθόνη" -#: ../vnc.html:192 ../vnc.html:199 +#: ../vnc.html:150 ../vnc.html:156 msgid "Settings" msgstr "Ρυθμίσεις" -#: ../vnc.html:202 +#: ../vnc.html:160 msgid "Shared Mode" msgstr "Κοινόχρηστη Λειτουργία" -#: ../vnc.html:205 +#: ../vnc.html:163 msgid "View Only" msgstr "Μόνο Θέαση" -#: ../vnc.html:209 +#: ../vnc.html:167 msgid "Clip to Window" msgstr "Αποκοπή στο όριο του Παράθυρου" -#: ../vnc.html:212 +#: ../vnc.html:170 msgid "Scaling Mode:" msgstr "Λειτουργία Κλιμάκωσης:" -#: ../vnc.html:214 +#: ../vnc.html:172 msgid "None" msgstr "Καμία" -#: ../vnc.html:215 +#: ../vnc.html:173 msgid "Local Scaling" msgstr "Τοπική Κλιμάκωση" -#: ../vnc.html:216 +#: ../vnc.html:174 msgid "Remote Resizing" msgstr "Απομακρυσμένη Αλλαγή μεγέθους" -#: ../vnc.html:221 +#: ../vnc.html:179 msgid "Advanced" msgstr "Για προχωρημένους" -#: ../vnc.html:224 +#: ../vnc.html:182 +msgid "Quality:" +msgstr "Ποιότητα:" + +#: ../vnc.html:186 +msgid "Compression level:" +msgstr "Επίπεδο συμπίεσης:" + +#: ../vnc.html:191 msgid "Repeater ID:" msgstr "Repeater ID:" -#: ../vnc.html:228 +#: ../vnc.html:195 msgid "WebSocket" msgstr "WebSocket" -#: ../vnc.html:231 +#: ../vnc.html:198 msgid "Encrypt" msgstr "Κρυπτογράφηση" -#: ../vnc.html:234 +#: ../vnc.html:201 msgid "Host:" msgstr "Όνομα διακομιστή:" -#: ../vnc.html:238 +#: ../vnc.html:205 msgid "Port:" msgstr "Πόρτα διακομιστή:" -#: ../vnc.html:242 +#: ../vnc.html:209 msgid "Path:" msgstr "Διαδρομή:" -#: ../vnc.html:249 +#: ../vnc.html:216 msgid "Automatic Reconnect" msgstr "Αυτόματη επανασύνδεση" -#: ../vnc.html:252 +#: ../vnc.html:219 msgid "Reconnect Delay (ms):" msgstr "Καθυστέρηση επανασύνδεσης (ms):" -#: ../vnc.html:258 +#: ../vnc.html:224 +msgid "Show Dot when No Cursor" +msgstr "Εμφάνιση Τελείας όταν δεν υπάρχει Δρομέας" + +#: ../vnc.html:229 msgid "Logging:" msgstr "Καταγραφή:" -#: ../vnc.html:270 +#: ../vnc.html:238 +msgid "Version:" +msgstr "Έκδοση:" + +#: ../vnc.html:246 msgid "Disconnect" msgstr "Αποσύνδεση" -#: ../vnc.html:289 +#: ../vnc.html:269 msgid "Connect" msgstr "Σύνδεση" -#: ../vnc.html:299 +#: ../vnc.html:278 +msgid "Server identity" +msgstr "Ταυτότητα Διακομιστή" + +#: ../vnc.html:281 +msgid "The server has provided the following identifying information:" +msgstr "Ο διακομιστής παρείχε την ακόλουθη πληροφορία ταυτοποίησης:" + +#: ../vnc.html:285 +msgid "Fingerprint:" +msgstr "Δακτυλικό αποτύπωμα:" + +#: ../vnc.html:288 +msgid "" +"Please verify that the information is correct and press \"Approve\". " +"Otherwise press \"Reject\"." +msgstr "" +"Παρακαλώ επαληθεύσετε ότι η πληροφορία είναι σωστή και πιέστε \"Αποδοχή\". " +"Αλλιώς πιέστε \"Απόρριψη\"." + +#: ../vnc.html:293 +msgid "Approve" +msgstr "Αποδοχή" + +#: ../vnc.html:294 +msgid "Reject" +msgstr "Απόρριψη" + +#: ../vnc.html:302 +msgid "Credentials" +msgstr "Διαπιστευτήρια" + +#: ../vnc.html:306 +msgid "Username:" +msgstr "Κωδικός Χρήστη:" + +#: ../vnc.html:310 msgid "Password:" msgstr "Κωδικός Πρόσβασης:" -#: ../vnc.html:313 +#: ../vnc.html:314 +msgid "Send Credentials" +msgstr "Αποστολή Διαπιστευτηρίων" + +#: ../vnc.html:323 msgid "Cancel" msgstr "Ακύρωση" -#: ../vnc.html:329 -msgid "Canvas not supported." -msgstr "Δεν υποστηρίζεται το στοιχείο Canvas" +#~ msgid "Password is required" +#~ msgstr "Απαιτείται ο κωδικός πρόσβασης" + +#~ msgid "viewport drag" +#~ msgstr "σύρσιμο θεατού πεδίου" + +#~ msgid "Active Mouse Button" +#~ msgstr "Ενεργό Πλήκτρο Ποντικιού" + +#~ msgid "No mousebutton" +#~ msgstr "Χωρίς Πλήκτρο Ποντικιού" + +#~ msgid "Left mousebutton" +#~ msgstr "Αριστερό Πλήκτρο Ποντικιού" + +#~ msgid "Middle mousebutton" +#~ msgstr "Μεσαίο Πλήκτρο Ποντικιού" + +#~ msgid "Right mousebutton" +#~ msgstr "Δεξί Πλήκτρο Ποντικιού" + +#~ msgid "Clear" +#~ msgstr "Καθάρισμα" + +#~ msgid "Canvas not supported." +#~ msgstr "Δεν υποστηρίζεται το στοιχείο Canvas" #~ msgid "Disconnect timeout" #~ msgstr "Παρέλευση χρονικού ορίου αποσύνδεσης" diff --git a/po/noVNC.pot b/po/noVNC.pot index 3641e3bc9..0f85a82e5 100644 --- a/po/noVNC.pot +++ b/po/noVNC.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: noVNC 1.4.0\n" +"Project-Id-Version: noVNC 1.5.0\n" "Report-Msgid-Bugs-To: novnc@googlegroups.com\n" -"POT-Creation-Date: 2022-12-27 15:24+0100\n" +"POT-Creation-Date: 2024-06-03 14:10+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,7 +18,8 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" #: ../app/ui.js:69 -msgid "HTTPS is required for full functionality" +msgid "" +"Running without HTTPS is not recommended, crashes or other issues are likely." msgstr "" #: ../app/ui.js:410 @@ -41,292 +42,296 @@ msgstr "" msgid "Must set host" msgstr "" -#: ../app/ui.js:1110 +#: ../app/ui.js:1052 +msgid "Failed to connect to server: " +msgstr "" + +#: ../app/ui.js:1118 msgid "Connected (encrypted) to " msgstr "" -#: ../app/ui.js:1112 +#: ../app/ui.js:1120 msgid "Connected (unencrypted) to " msgstr "" -#: ../app/ui.js:1135 +#: ../app/ui.js:1143 msgid "Something went wrong, connection is closed" msgstr "" -#: ../app/ui.js:1138 +#: ../app/ui.js:1146 msgid "Failed to connect to server" msgstr "" -#: ../app/ui.js:1150 +#: ../app/ui.js:1158 msgid "Disconnected" msgstr "" -#: ../app/ui.js:1165 +#: ../app/ui.js:1173 msgid "New connection has been rejected with reason: " msgstr "" -#: ../app/ui.js:1168 +#: ../app/ui.js:1176 msgid "New connection has been rejected" msgstr "" -#: ../app/ui.js:1234 +#: ../app/ui.js:1242 msgid "Credentials are required" msgstr "" -#: ../vnc.html:57 +#: ../vnc.html:55 msgid "noVNC encountered an error:" msgstr "" -#: ../vnc.html:67 +#: ../vnc.html:65 msgid "Hide/Show the control bar" msgstr "" -#: ../vnc.html:76 +#: ../vnc.html:74 msgid "Drag" msgstr "" -#: ../vnc.html:76 +#: ../vnc.html:74 msgid "Move/Drag Viewport" msgstr "" -#: ../vnc.html:82 +#: ../vnc.html:80 msgid "Keyboard" msgstr "" -#: ../vnc.html:82 +#: ../vnc.html:80 msgid "Show Keyboard" msgstr "" -#: ../vnc.html:87 +#: ../vnc.html:85 msgid "Extra keys" msgstr "" -#: ../vnc.html:87 +#: ../vnc.html:85 msgid "Show Extra Keys" msgstr "" -#: ../vnc.html:92 +#: ../vnc.html:90 msgid "Ctrl" msgstr "" -#: ../vnc.html:92 +#: ../vnc.html:90 msgid "Toggle Ctrl" msgstr "" -#: ../vnc.html:95 +#: ../vnc.html:93 msgid "Alt" msgstr "" -#: ../vnc.html:95 +#: ../vnc.html:93 msgid "Toggle Alt" msgstr "" -#: ../vnc.html:98 +#: ../vnc.html:96 msgid "Toggle Windows" msgstr "" -#: ../vnc.html:98 +#: ../vnc.html:96 msgid "Windows" msgstr "" -#: ../vnc.html:101 +#: ../vnc.html:99 msgid "Send Tab" msgstr "" -#: ../vnc.html:101 +#: ../vnc.html:99 msgid "Tab" msgstr "" -#: ../vnc.html:104 +#: ../vnc.html:102 msgid "Esc" msgstr "" -#: ../vnc.html:104 +#: ../vnc.html:102 msgid "Send Escape" msgstr "" -#: ../vnc.html:107 +#: ../vnc.html:105 msgid "Ctrl+Alt+Del" msgstr "" -#: ../vnc.html:107 +#: ../vnc.html:105 msgid "Send Ctrl-Alt-Del" msgstr "" -#: ../vnc.html:114 +#: ../vnc.html:112 msgid "Shutdown/Reboot" msgstr "" -#: ../vnc.html:114 +#: ../vnc.html:112 msgid "Shutdown/Reboot..." msgstr "" -#: ../vnc.html:120 +#: ../vnc.html:118 msgid "Power" msgstr "" -#: ../vnc.html:122 +#: ../vnc.html:120 msgid "Shutdown" msgstr "" -#: ../vnc.html:123 +#: ../vnc.html:121 msgid "Reboot" msgstr "" -#: ../vnc.html:124 +#: ../vnc.html:122 msgid "Reset" msgstr "" -#: ../vnc.html:129 ../vnc.html:135 +#: ../vnc.html:127 ../vnc.html:133 msgid "Clipboard" msgstr "" -#: ../vnc.html:137 +#: ../vnc.html:135 msgid "Edit clipboard content in the textarea below." msgstr "" -#: ../vnc.html:145 +#: ../vnc.html:143 msgid "Full Screen" msgstr "" -#: ../vnc.html:150 ../vnc.html:156 +#: ../vnc.html:148 ../vnc.html:154 msgid "Settings" msgstr "" -#: ../vnc.html:160 +#: ../vnc.html:158 msgid "Shared Mode" msgstr "" -#: ../vnc.html:163 +#: ../vnc.html:161 msgid "View Only" msgstr "" -#: ../vnc.html:167 +#: ../vnc.html:165 msgid "Clip to Window" msgstr "" -#: ../vnc.html:170 +#: ../vnc.html:168 msgid "Scaling Mode:" msgstr "" -#: ../vnc.html:172 +#: ../vnc.html:170 msgid "None" msgstr "" -#: ../vnc.html:173 +#: ../vnc.html:171 msgid "Local Scaling" msgstr "" -#: ../vnc.html:174 +#: ../vnc.html:172 msgid "Remote Resizing" msgstr "" -#: ../vnc.html:179 +#: ../vnc.html:177 msgid "Advanced" msgstr "" -#: ../vnc.html:182 +#: ../vnc.html:180 msgid "Quality:" msgstr "" -#: ../vnc.html:186 +#: ../vnc.html:184 msgid "Compression level:" msgstr "" -#: ../vnc.html:191 +#: ../vnc.html:189 msgid "Repeater ID:" msgstr "" -#: ../vnc.html:195 +#: ../vnc.html:193 msgid "WebSocket" msgstr "" -#: ../vnc.html:198 +#: ../vnc.html:196 msgid "Encrypt" msgstr "" -#: ../vnc.html:201 +#: ../vnc.html:199 msgid "Host:" msgstr "" -#: ../vnc.html:205 +#: ../vnc.html:203 msgid "Port:" msgstr "" -#: ../vnc.html:209 +#: ../vnc.html:207 msgid "Path:" msgstr "" -#: ../vnc.html:216 +#: ../vnc.html:214 msgid "Automatic Reconnect" msgstr "" -#: ../vnc.html:219 +#: ../vnc.html:217 msgid "Reconnect Delay (ms):" msgstr "" -#: ../vnc.html:224 +#: ../vnc.html:222 msgid "Show Dot when No Cursor" msgstr "" -#: ../vnc.html:229 +#: ../vnc.html:227 msgid "Logging:" msgstr "" -#: ../vnc.html:238 +#: ../vnc.html:236 msgid "Version:" msgstr "" -#: ../vnc.html:246 +#: ../vnc.html:244 msgid "Disconnect" msgstr "" -#: ../vnc.html:269 +#: ../vnc.html:267 msgid "Connect" msgstr "" -#: ../vnc.html:278 +#: ../vnc.html:276 msgid "Server identity" msgstr "" -#: ../vnc.html:281 +#: ../vnc.html:279 msgid "The server has provided the following identifying information:" msgstr "" -#: ../vnc.html:285 +#: ../vnc.html:283 msgid "Fingerprint:" msgstr "" -#: ../vnc.html:288 +#: ../vnc.html:286 msgid "" "Please verify that the information is correct and press \"Approve\". " "Otherwise press \"Reject\"." msgstr "" -#: ../vnc.html:293 +#: ../vnc.html:291 msgid "Approve" msgstr "" -#: ../vnc.html:294 +#: ../vnc.html:292 msgid "Reject" msgstr "" -#: ../vnc.html:302 +#: ../vnc.html:300 msgid "Credentials" msgstr "" -#: ../vnc.html:306 +#: ../vnc.html:304 msgid "Username:" msgstr "" -#: ../vnc.html:310 +#: ../vnc.html:308 msgid "Password:" msgstr "" -#: ../vnc.html:314 +#: ../vnc.html:312 msgid "Send Credentials" msgstr "" -#: ../vnc.html:323 +#: ../vnc.html:321 msgid "Cancel" msgstr "" diff --git a/po/po2js b/po/po2js index fc6e88103..e293deda6 100755 --- a/po/po2js +++ b/po/po2js @@ -32,11 +32,13 @@ if (opt.argv.length != 2) { const data = po2json.parseFileSync(opt.argv[0]); -const bodyPart = Object.keys(data).filter(msgid => msgid !== "").map((msgid) => { - if (msgid === "") return; - const msgstr = data[msgid][1]; - return " " + JSON.stringify(msgid) + ": " + JSON.stringify(msgstr); -}).join(",\n"); +const bodyPart = Object.keys(data) + .filter(msgid => msgid !== "") + .filter(msgid => data[msgid][1] !== "") + .map((msgid) => { + const msgstr = data[msgid][1]; + return " " + JSON.stringify(msgid) + ": " + JSON.stringify(msgstr); + }).join(",\n"); const output = "{\n" + bodyPart + "\n}"; diff --git a/po/sv.po b/po/sv.po index 972e40004..85c4e3054 100644 --- a/po/sv.po +++ b/po/sv.po @@ -8,20 +8,23 @@ msgid "" msgstr "" "Project-Id-Version: noVNC 1.3.0\n" "Report-Msgid-Bugs-To: novnc@googlegroups.com\n" -"POT-Creation-Date: 2023-01-20 12:54+0100\n" -"PO-Revision-Date: 2023-01-20 12:58+0100\n" -"Last-Translator: Samuel Mannehed \n" +"POT-Creation-Date: 2024-06-03 14:10+0200\n" +"PO-Revision-Date: 2024-06-18 13:52+0200\n" +"Last-Translator: Pierre Ossman \n" "Language-Team: none\n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.2.2\n" +"X-Generator: Poedit 3.4.4\n" #: ../app/ui.js:69 -msgid "HTTPS is required for full functionality" -msgstr "HTTPS krävs för full funktionalitet" +msgid "" +"Running without HTTPS is not recommended, crashes or other issues are likely." +msgstr "" +"Det är ej rekommenderat att köra utan HTTPS, krascher och andra problem är " +"troliga." #: ../app/ui.js:410 msgid "Connecting..." @@ -43,35 +46,39 @@ msgstr "Internt fel" msgid "Must set host" msgstr "Du måste specifiera en värd" -#: ../app/ui.js:1110 +#: ../app/ui.js:1052 +msgid "Failed to connect to server: " +msgstr "Misslyckades att ansluta till servern: " + +#: ../app/ui.js:1118 msgid "Connected (encrypted) to " msgstr "Ansluten (krypterat) till " -#: ../app/ui.js:1112 +#: ../app/ui.js:1120 msgid "Connected (unencrypted) to " msgstr "Ansluten (okrypterat) till " -#: ../app/ui.js:1135 +#: ../app/ui.js:1143 msgid "Something went wrong, connection is closed" msgstr "Något gick fel, anslutningen avslutades" -#: ../app/ui.js:1138 +#: ../app/ui.js:1146 msgid "Failed to connect to server" msgstr "Misslyckades att ansluta till servern" -#: ../app/ui.js:1150 +#: ../app/ui.js:1158 msgid "Disconnected" msgstr "Frånkopplad" -#: ../app/ui.js:1165 +#: ../app/ui.js:1173 msgid "New connection has been rejected with reason: " msgstr "Ny anslutning har blivit nekad med följande skäl: " -#: ../app/ui.js:1168 +#: ../app/ui.js:1176 msgid "New connection has been rejected" msgstr "Ny anslutning har blivit nekad" -#: ../app/ui.js:1234 +#: ../app/ui.js:1242 msgid "Credentials are required" msgstr "Användaruppgifter krävs" @@ -304,8 +311,8 @@ msgid "" "Please verify that the information is correct and press \"Approve\". " "Otherwise press \"Reject\"." msgstr "" -"Kontrollera att informationen är korrekt och tryck sedan " -"\"Godkänn\". Tryck annars \"Neka\"." +"Kontrollera att informationen är korrekt och tryck sedan \"Godkänn\". Tryck " +"annars \"Neka\"." #: ../vnc.html:291 msgid "Approve" @@ -335,5 +342,8 @@ msgstr "Skicka Användaruppgifter" msgid "Cancel" msgstr "Avbryt" +#~ msgid "HTTPS is required for full functionality" +#~ msgstr "HTTPS krävs för full funktionalitet" + #~ msgid "Clear" #~ msgstr "Rensa" diff --git a/po/zh_CN.po b/po/zh_CN.po index ede9d4414..caae28504 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -15,58 +15,42 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../app/ui.js:395 +#: ../app/ui.js:430 msgid "Connecting..." msgstr "连接中..." -#: ../app/ui.js:402 -msgid "Disconnecting..." -msgstr "正在断开连接..." - -#: ../app/ui.js:408 -msgid "Reconnecting..." -msgstr "重新连接中..." - -#: ../app/ui.js:413 -msgid "Internal error" -msgstr "内部错误" - -#: ../app/ui.js:1015 -msgid "Must set host" -msgstr "请提供主机名" - -#: ../app/ui.js:1097 +#: ../app/ui.js:438 msgid "Connected (encrypted) to " -msgstr "已连接到(加密)" +msgstr "已连接(已加密)到" -#: ../app/ui.js:1099 +#: ../app/ui.js:440 msgid "Connected (unencrypted) to " -msgstr "已连接到(未加密)" +msgstr "已连接(未加密)到" -#: ../app/ui.js:1120 -msgid "Something went wrong, connection is closed" -msgstr "发生错误,连接已关闭" - -#: ../app/ui.js:1123 -msgid "Failed to connect to server" -msgstr "无法连接到服务器" +#: ../app/ui.js:446 +msgid "Disconnecting..." +msgstr "正在断开连接..." -#: ../app/ui.js:1133 +#: ../app/ui.js:450 msgid "Disconnected" msgstr "已断开连接" -#: ../app/ui.js:1146 -msgid "New connection has been rejected with reason: " -msgstr "连接被拒绝,原因:" +#: ../app/ui.js:1052 ../core/rfb.js:248 +msgid "Must set host" +msgstr "必须设置主机" -#: ../app/ui.js:1149 -msgid "New connection has been rejected" -msgstr "连接被拒绝" +#: ../app/ui.js:1101 +msgid "Reconnecting..." +msgstr "重新连接中..." -#: ../app/ui.js:1170 +#: ../app/ui.js:1140 msgid "Password is required" msgstr "请提供密码" +#: ../core/rfb.js:548 +msgid "Disconnect timeout" +msgstr "超时断开" + #: ../vnc.html:89 msgid "noVNC encountered an error:" msgstr "noVNC 遇到一个错误:" @@ -77,31 +61,31 @@ msgstr "显示/隐藏控制栏" #: ../vnc.html:106 msgid "Move/Drag Viewport" -msgstr "拖放显示范围" +msgstr "移动/拖动窗口" #: ../vnc.html:106 msgid "viewport drag" -msgstr "显示范围拖放" +msgstr "窗口拖动" #: ../vnc.html:112 ../vnc.html:115 ../vnc.html:118 ../vnc.html:121 msgid "Active Mouse Button" -msgstr "启动鼠标按鍵" +msgstr "启动鼠标按键" #: ../vnc.html:112 msgid "No mousebutton" -msgstr "禁用鼠标按鍵" +msgstr "禁用鼠标按键" #: ../vnc.html:115 msgid "Left mousebutton" -msgstr "鼠标左鍵" +msgstr "鼠标左键" #: ../vnc.html:118 msgid "Middle mousebutton" -msgstr "鼠标中鍵" +msgstr "鼠标中键" #: ../vnc.html:121 msgid "Right mousebutton" -msgstr "鼠标右鍵" +msgstr "鼠标右键" #: ../vnc.html:124 msgid "Keyboard" @@ -127,6 +111,10 @@ msgstr "Ctrl" msgid "Toggle Ctrl" msgstr "切换 Ctrl" +#: ../vnc.html:136 +msgid "Edit clipboard content in the textarea below." +msgstr "在下面的文本区域中编辑剪贴板内容。" + #: ../vnc.html:139 msgid "Alt" msgstr "Alt" @@ -153,19 +141,19 @@ msgstr "发送 Escape 键" #: ../vnc.html:148 msgid "Ctrl+Alt+Del" -msgstr "Ctrl-Alt-Del" +msgstr "Ctrl+Alt+Del" #: ../vnc.html:148 msgid "Send Ctrl-Alt-Del" -msgstr "发送 Ctrl-Alt-Del 键" +msgstr "发送 Ctrl+Alt+Del 键" #: ../vnc.html:156 msgid "Shutdown/Reboot" -msgstr "关机/重新启动" +msgstr "关机/重启" #: ../vnc.html:156 msgid "Shutdown/Reboot..." -msgstr "关机/重新启动..." +msgstr "关机/重启..." #: ../vnc.html:162 msgid "Power" @@ -177,7 +165,7 @@ msgstr "关机" #: ../vnc.html:165 msgid "Reboot" -msgstr "重新启动" +msgstr "重启" #: ../vnc.html:166 msgid "Reset" @@ -199,6 +187,10 @@ msgstr "全屏" msgid "Settings" msgstr "设置" +#: ../vnc.html:200 +msgid "Encrypt" +msgstr "加密" + #: ../vnc.html:202 msgid "Shared Mode" msgstr "分享模式" @@ -224,61 +216,69 @@ msgid "Local Scaling" msgstr "本地缩放" #: ../vnc.html:216 +msgid "Local Downscaling" +msgstr "降低本地尺寸" + +#: ../vnc.html:217 msgid "Remote Resizing" msgstr "远程调整大小" -#: ../vnc.html:221 +#: ../vnc.html:222 msgid "Advanced" msgstr "高级" -#: ../vnc.html:224 +#: ../vnc.html:225 +msgid "Local Cursor" +msgstr "本地光标" + +#: ../vnc.html:229 msgid "Repeater ID:" msgstr "中继站 ID" -#: ../vnc.html:228 +#: ../vnc.html:233 msgid "WebSocket" msgstr "WebSocket" -#: ../vnc.html:231 -msgid "Encrypt" -msgstr "加密" - -#: ../vnc.html:234 +#: ../vnc.html:239 msgid "Host:" msgstr "主机:" -#: ../vnc.html:238 +#: ../vnc.html:243 msgid "Port:" msgstr "端口:" -#: ../vnc.html:242 +#: ../vnc.html:247 msgid "Path:" msgstr "路径:" -#: ../vnc.html:249 +#: ../vnc.html:254 msgid "Automatic Reconnect" msgstr "自动重新连接" -#: ../vnc.html:252 +#: ../vnc.html:257 msgid "Reconnect Delay (ms):" msgstr "重新连接间隔 (ms):" -#: ../vnc.html:258 +#: ../vnc.html:263 msgid "Logging:" msgstr "日志级别:" -#: ../vnc.html:270 +#: ../vnc.html:275 msgid "Disconnect" -msgstr "中断连接" +msgstr "断开连接" -#: ../vnc.html:289 +#: ../vnc.html:294 msgid "Connect" msgstr "连接" -#: ../vnc.html:299 +#: ../vnc.html:304 msgid "Password:" msgstr "密码:" -#: ../vnc.html:313 +#: ../vnc.html:318 msgid "Cancel" msgstr "取消" + +#: ../vnc.html:334 +msgid "Canvas not supported." +msgstr "不支持 Canvas。" \ No newline at end of file diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index ccf618930..82d52de4d 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -42,7 +42,7 @@ parts: - jq websockify: - source: https://github.com/novnc/websockify/archive/v0.11.0.tar.gz + source: https://github.com/novnc/websockify/archive/v0.12.0.tar.gz plugin: python stage-packages: - python3-numpy diff --git a/tests/.eslintrc b/tests/.eslintrc deleted file mode 100644 index 545fa2ed2..000000000 --- a/tests/.eslintrc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "env": { - "node": true, - "mocha": true - }, - "globals": { - "chai": false, - "sinon": false - }, - "rules": { - "prefer-arrow-callback": 0, - // Too many anonymous callbacks - "func-names": "off", - } -} diff --git a/tests/assertions.js b/tests/assertions.js index 739f63753..a70122717 100644 --- a/tests/assertions.js +++ b/tests/assertions.js @@ -1,3 +1,12 @@ +import * as chai from '../node_modules/chai/chai.js'; +import sinon from '../node_modules/sinon/pkg/sinon-esm.js'; +import sinonChai from '../node_modules/sinon-chai/lib/sinon-chai.js'; + +window.expect = chai.expect; + +window.sinon = sinon; +chai.use(sinonChai); + // noVNC specific assertions chai.use(function (_chai, utils) { function _equal(a, b) { diff --git a/tests/test.base64.js b/tests/test.base64.js index 04bd207b7..e5644dcdb 100644 --- a/tests/test.base64.js +++ b/tests/test.base64.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Base64 from '../core/base64.js'; describe('Base64 Tools', function () { diff --git a/tests/test.browser.js b/tests/test.browser.js index 3b2299f63..692cc23b2 100644 --- a/tests/test.browser.js +++ b/tests/test.browser.js @@ -1,6 +1,3 @@ -/* eslint-disable no-console */ -const expect = chai.expect; - import { isMac, isWindows, isIOS, isAndroid, isChromeOS, isSafari, isFirefox, isChrome, isChromium, isOpera, isEdge, isGecko, isWebKit, isBlink } from '../core/util/browser.js'; diff --git a/tests/test.copyrect.js b/tests/test.copyrect.js index a10cddce7..60c395287 100644 --- a/tests/test.copyrect.js +++ b/tests/test.copyrect.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Websock from '../core/websock.js'; import Display from '../core/display.js'; diff --git a/tests/test.deflator.js b/tests/test.deflator.js index 12e8a46bf..b565b9075 100644 --- a/tests/test.deflator.js +++ b/tests/test.deflator.js @@ -1,6 +1,3 @@ -/* eslint-disable no-console */ -const expect = chai.expect; - import { inflateInit, inflate } from "../vendor/pako/lib/zlib/inflate.js"; import ZStream from "../vendor/pako/lib/zlib/zstream.js"; import Deflator from "../core/deflator.js"; diff --git a/tests/test.display.js b/tests/test.display.js index e6c0406f9..d2c51793b 100644 --- a/tests/test.display.js +++ b/tests/test.display.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Base64 from '../core/base64.js'; import Display from '../core/display.js'; diff --git a/tests/test.gesturehandler.js b/tests/test.gesturehandler.js index 73356be36..d2e27ed2a 100644 --- a/tests/test.gesturehandler.js +++ b/tests/test.gesturehandler.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import EventTargetMixin from '../core/util/eventtarget.js'; import GestureHandler from '../core/input/gesturehandler.js'; diff --git a/tests/test.helper.js b/tests/test.helper.js index 9995973fd..2c8720c77 100644 --- a/tests/test.helper.js +++ b/tests/test.helper.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import keysyms from '../core/input/keysymdef.js'; import * as KeyboardUtil from "../core/input/util.js"; diff --git a/tests/test.hextile.js b/tests/test.hextile.js index cbe6f7b5a..f788fd4dc 100644 --- a/tests/test.hextile.js +++ b/tests/test.hextile.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Websock from '../core/websock.js'; import Display from '../core/display.js'; diff --git a/tests/test.inflator.js b/tests/test.inflator.js index 533bcd865..11a02f2f4 100644 --- a/tests/test.inflator.js +++ b/tests/test.inflator.js @@ -1,6 +1,3 @@ -/* eslint-disable no-console */ -const expect = chai.expect; - import { deflateInit, deflate, Z_FULL_FLUSH } from "../vendor/pako/lib/zlib/deflate.js"; import ZStream from "../vendor/pako/lib/zlib/zstream.js"; import Inflator from "../core/inflator.js"; diff --git a/tests/test.int.js b/tests/test.int.js index 954fd279f..378ebd589 100644 --- a/tests/test.int.js +++ b/tests/test.int.js @@ -1,6 +1,3 @@ -/* eslint-disable no-console */ -const expect = chai.expect; - import { toUnsigned32bit, toSigned32bit } from '../core/util/int.js'; describe('Integer casting', function () { diff --git a/tests/test.jpeg.js b/tests/test.jpeg.js index 8dee48912..5cc153f90 100644 --- a/tests/test.jpeg.js +++ b/tests/test.jpeg.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Websock from '../core/websock.js'; import Display from '../core/display.js'; diff --git a/tests/test.keyboard.js b/tests/test.keyboard.js index efc84c306..11c8b6eb7 100644 --- a/tests/test.keyboard.js +++ b/tests/test.keyboard.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Keyboard from '../core/input/keyboard.js'; describe('Key Event Handling', function () { @@ -480,6 +478,22 @@ describe('Key Event Handling', function () { expect(kbd.onkeyevent).to.not.have.been.called; }); + it('should release ControlLeft on blur', function () { + const kbd = new Keyboard(document); + kbd.onkeyevent = sinon.spy(); + kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1})); + expect(kbd.onkeyevent).to.not.have.been.called; + kbd._allKeysUp(); + expect(kbd.onkeyevent).to.have.been.calledTwice; + expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xffe3, "ControlLeft", true); + expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xffe3, "ControlLeft", false); + + // Check that the timer is properly dead + kbd.onkeyevent.resetHistory(); + this.clock.tick(100); + expect(kbd.onkeyevent).to.not.have.been.called; + }); + it('should generate AltGraph for quick Ctrl+Alt sequence', function () { const kbd = new Keyboard(document); kbd.onkeyevent = sinon.spy(); diff --git a/tests/test.localization.js b/tests/test.localization.js index 916ff8462..a1cb45474 100644 --- a/tests/test.localization.js +++ b/tests/test.localization.js @@ -1,4 +1,3 @@ -const expect = chai.expect; import _, { Localizer, l10n } from '../app/localization.js'; describe('Localization', function () { diff --git a/tests/test.raw.js b/tests/test.raw.js index 4a634ccd0..19b2377f7 100644 --- a/tests/test.raw.js +++ b/tests/test.raw.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Websock from '../core/websock.js'; import Display from '../core/display.js'; diff --git a/tests/test.rfb.js b/tests/test.rfb.js index 62b80ca3f..2be3bfbfc 100644 --- a/tests/test.rfb.js +++ b/tests/test.rfb.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import RFB from '../core/rfb.js'; import Websock from '../core/websock.js'; import ZStream from "../vendor/pako/lib/zlib/zstream.js"; diff --git a/tests/test.rre.js b/tests/test.rre.js index c55d7f397..7b5f73d0e 100644 --- a/tests/test.rre.js +++ b/tests/test.rre.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Websock from '../core/websock.js'; import Display from '../core/display.js'; diff --git a/tests/test.tight.js b/tests/test.tight.js index b3457a88b..3d6b555da 100644 --- a/tests/test.tight.js +++ b/tests/test.tight.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Websock from '../core/websock.js'; import Display from '../core/display.js'; @@ -228,12 +226,59 @@ describe('Tight Decoder', function () { expect(display).to.have.displayed(targetData); }); - it.skip('should handle uncompressed gradient rects', function () { - // Not implemented yet + it('should handle uncompressed gradient rects', function () { + let done; + let blueData = [ 0x40, 0x02, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00 ]; + let greenData = [ 0x40, 0x02, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 ]; + + done = testDecodeRect(decoder, 0, 0, 2, 1, blueData, display, 24); + expect(done).to.be.true; + done = testDecodeRect(decoder, 0, 1, 2, 1, blueData, display, 24); + expect(done).to.be.true; + done = testDecodeRect(decoder, 2, 0, 2, 1, greenData, display, 24); + expect(done).to.be.true; + done = testDecodeRect(decoder, 2, 1, 2, 1, greenData, display, 24); + expect(done).to.be.true; + done = testDecodeRect(decoder, 0, 2, 2, 1, greenData, display, 24); + expect(done).to.be.true; + done = testDecodeRect(decoder, 0, 3, 2, 1, greenData, display, 24); + expect(done).to.be.true; + done = testDecodeRect(decoder, 2, 2, 2, 1, blueData, display, 24); + expect(done).to.be.true; + done = testDecodeRect(decoder, 2, 3, 2, 1, blueData, display, 24); + expect(done).to.be.true; + + let targetData = new Uint8Array([ + 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, + 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, + 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, + 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 + ]); + + expect(display).to.have.displayed(targetData); }); - it.skip('should handle compressed gradient rects', function () { - // Not implemented yet + it('should handle compressed gradient rects', function () { + let data = [ + // Control byte + 0x40, 0x02, + // Pixels (compressed) + 0x18, + 0x78, 0x9c, 0x62, 0x60, 0xf8, 0xcf, 0x00, 0x04, + 0xff, 0x19, 0x19, 0xd0, 0x00, 0x44, 0x84, 0xf1, + 0x3f, 0x9a, 0x30, 0x00, 0x00, 0x00, 0xff, 0xff ]; + + let done = testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24); + + let targetData = new Uint8Array([ + 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, + 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, + 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, + 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 + ]); + + expect(done).to.be.true; + expect(display).to.have.displayed(targetData); }); it('should handle empty copy rects', function () { @@ -275,6 +320,25 @@ describe('Tight Decoder', function () { expect(display).to.have.displayed(targetData); }); + it('should handle empty gradient rects', function () { + display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); + display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); + display.fillRect(0, 2, 2, 2, [ 0x00, 0xff, 0x00 ]); + + let done = testDecodeRect(decoder, 1, 2, 0, 0, + [ 0x40, 0x02 ], display, 24); + + let targetData = new Uint8Array([ + 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, + 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, + 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, + 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255 + ]); + + expect(done).to.be.true; + expect(display).to.have.displayed(targetData); + }); + it('should handle empty fill rects', function () { display.fillRect(0, 0, 4, 4, [ 0x00, 0x00, 0xff ]); display.fillRect(2, 0, 2, 2, [ 0x00, 0xff, 0x00 ]); diff --git a/tests/test.tightpng.js b/tests/test.tightpng.js index 02c66d93b..e7edc8fa6 100644 --- a/tests/test.tightpng.js +++ b/tests/test.tightpng.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Websock from '../core/websock.js'; import Display from '../core/display.js'; diff --git a/tests/test.util.js b/tests/test.util.js index cd61f248a..eb7240951 100644 --- a/tests/test.util.js +++ b/tests/test.util.js @@ -1,6 +1,4 @@ /* eslint-disable no-console */ -const expect = chai.expect; - import * as Log from '../core/util/logging.js'; import { encodeUTF8, decodeUTF8 } from '../core/util/strings.js'; diff --git a/tests/test.websock.js b/tests/test.websock.js index dc361b749..53145b360 100644 --- a/tests/test.websock.js +++ b/tests/test.websock.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Websock from '../core/websock.js'; import FakeWebSocket from './fake.websocket.js'; diff --git a/tests/test.webutil.js b/tests/test.webutil.js index df8227aef..9151a0603 100644 --- a/tests/test.webutil.js +++ b/tests/test.webutil.js @@ -1,7 +1,5 @@ /* jshint expr: true */ -const expect = chai.expect; - import * as WebUtil from '../app/webutil.js'; describe('WebUtil', function () { @@ -182,16 +180,15 @@ describe('WebUtil', function () { window.chrome = chrome; }); - const csSandbox = sinon.createSandbox(); - beforeEach(function () { settings = {}; - csSandbox.spy(window.chrome.storage.sync, 'set'); - csSandbox.spy(window.chrome.storage.sync, 'remove'); + sinon.spy(window.chrome.storage.sync, 'set'); + sinon.spy(window.chrome.storage.sync, 'remove'); return WebUtil.initSettings(); }); afterEach(function () { - csSandbox.restore(); + window.chrome.storage.sync.set.restore(); + window.chrome.storage.sync.remove.restore(); }); describe('writeSetting', function () { diff --git a/tests/test.zrle.js b/tests/test.zrle.js index be0464093..f7c6089d5 100644 --- a/tests/test.zrle.js +++ b/tests/test.zrle.js @@ -1,5 +1,3 @@ -const expect = chai.expect; - import Websock from '../core/websock.js'; import Display from '../core/display.js'; diff --git a/utils/.eslintrc b/utils/.eslintrc deleted file mode 100644 index b7dc129f1..000000000 --- a/utils/.eslintrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "env": { - "node": true - }, - "rules": { - "no-console": 0 - } -} \ No newline at end of file diff --git a/vnc.html b/vnc.html index 23d90d207..1ea615634 100644 --- a/vnc.html +++ b/vnc.html @@ -16,6 +16,7 @@ noVNC +