include "sciter:reactor.tis"; var handler = $(#handler) || view; try { view.windowIcon = self.url(handler.get_icon()); } catch(e) {} var OS = view.mediaVar("platform"); var is_osx = OS == "OSX"; var is_win = OS == "Windows"; var is_linux = OS == "Linux"; var is_file_transfer; var is_xfce = false; try { is_xfce = handler.is_xfce(); } catch(e) {} function isEnterKey(evt) { return (evt.keyCode == Event.VK_ENTER || (is_osx && evt.keyCode == 0x4C) || (is_linux && evt.keyCode == 65421)); } function getScaleFactor() { if (!is_win) return 1; return self.toPixels(10000dip) / 10000.; } var scaleFactor = getScaleFactor(); view << event resolutionchange { scaleFactor = getScaleFactor(); } function scaleIt(x) { return (x * scaleFactor).toInteger(); } stdout.println("scaleFactor", scaleFactor); function translate(name) { try { return handler.t(name); } catch(_) { return name; } } function hashCode(str) { var hash = 160 << 16 + 114 << 8 + 91; for (var i = 0; i < str.length; i += 1) { hash = str.charCodeAt(i) + ((hash << 5) - hash); } return hash % 16777216; } function intToRGB(i, a = 1) { return 'rgba(' + ((i >> 16) & 0xFF) + ', ' + ((i >> 8) & 0x7F) + ',' + (i & 0xFF) + ',' + a + ')'; } function string2RGB(s, a = 1) { return intToRGB(hashCode(s), a); } function getTime() { var now = new Date(); return now.valueOf(); } function platformSvg(platform, color) { platform = (platform || "").toLowerCase(); if (platform == "linux") { return ; } if (platform == "mac os") { return ; } if (platform == "android") { return ; } return ; } function centerize(w, h) { var (sx, sy, sw, sh) = view.screenBox(#workarea, #rectw); if (w > sw) w = sw; if (h > sh) h = sh; var x = (sx + sw - w) / 2; var y = (sy + sh - h) / 2; view.move(x, y, w, h); } function setWindowButontsAndIcon(only_min=false) { if (only_min) { $(div.window-buttons).content(
); } else { $(div.window-buttons).content(
); } $(div.window-icon>icon).style.set { "background-image": "url('" + handler.get_icon() + "')", }; } function adjustBorder() { if (is_osx) { if (view.windowState == View.WINDOW_FULL_SCREEN) { $(header).style.set { display: "none", }; } else { $(header).style.set { display: "block", padding: "0", }; } return; } if (view.windowState == view.WINDOW_MAXIMIZED) { self.style.set { border: "window-frame-width solid transparent", }; } else if (view.windowState == view.WINDOW_FULL_SCREEN) { self.style.set { border: "none", }; } else { self.style.set { border: "black solid 1px", }; } var el = $(button#maximize); if (el) el.attributes.toggleClass("restore", view.windowState == View.WINDOW_MAXIMIZED); el = $(span#fullscreen); if (el) el.attributes.toggleClass("active", view.windowState == View.WINDOW_FULL_SCREEN); } var svg_checkmark = ; var svg_edit = ; var svg_eye = ; var svg_send = ; var svg_chat = ; var svg_keyboard = ; function scrollToBottom(el) { var y = el.box(#height, #content) - el.box(#height, #client); el.scrollTo(0, y); } function getNowStr() { var now = new Date(); return String.printf("%02d:%02d:%02d", now.hour, now.minute, now.second); } /******************** start of chatbox ****************************************/ class ChatBox: Reactor.Component { this var msgs = []; this var callback; function this(params) { if (params) { this.msgs = params.msgs || []; this.callback = params.callback; } } function renderMsg(msg) { var cls = msg.name == "me" ? "right-side msg" : "left-side msg"; return
{msg.name == "me" ?
{msg.time + " "} me
:
{msg.name} {" " + msg.time}
}
{msg.text}
; } function render() { var me = this; var msgs = this.msgs.map(function(msg) { return me.renderMsg(msg); }); self.timer(1ms, function() { scrollToBottom(me.msgs); }); return
{msgs}
{svg_send}
; } function send() { var el = this.$(input); var value = (el.value || "").trim(); el.value = ""; if (!value) return; if (this.callback) this.callback(value); } event keydown $(input) (evt) { if (!evt.shortcutKey) { if (isEnterKey(evt)) { this.send(); } } } event click $(div.send span) { this.send(); view.focus = $(input); } } /******************** end of chatbox ****************************************/ /******************** start of msgbox ****************************************/ var remember_password = false; var last_msgbox_tag = ""; function msgbox(type, title, content, link="", callback=null, height=180, width=500, hasRetry=false, contentStyle="") { $(body).scrollTo(0, 0); if (!type) { closeMsgbox(); return; } var remember = false; try { remember = handler.get_remember(); } catch(e) {} var auto_login = false; try { auto_login = handler.get_option("auto-login") != ''; } catch(e) {} width += is_xfce ? 50 : 0; height += is_xfce ? 50 : 0; if (type.indexOf("input-password") >= 0) { callback = function (res) { if (!res) { view.close(); return; } handler.login(res.password, res.remember); if (!is_port_forward) { // Specially handling file transfer for no permission hanging issue (including 60ms // timer in setPermission. // For wrong password input hanging issue, we can not use handler.msgbox. // But how about wrong password for file transfer? if (is_file_transfer) handler.msgbox("connecting", "Connecting...", "Logging in..."); else msgbox("connecting", "Connecting...", "Logging in..."); } }; } else if (type.indexOf("custom") < 0 && !is_port_forward && !callback) { callback = function() { view.close(); } } last_msgbox_tag = type + "-" + title + "-" + content + "-" + link; $(#msgbox).content(); } function connecting() { handler.msgbox("connecting", "Connecting...", "Connection in progress. Please wait."); } handler.msgbox = function(type, title, text, link = "", hasRetry=false) { // crash somehow (when input wrong password), even with small time, for example, 1ms self.timer(60ms, function() { msgbox(type, title, text, link, null, 180, 500, hasRetry); }); } handler.cancel_msgbox = function(tag) { if (last_msgbox_tag == tag) { closeMsgbox(); } } var reconnectTimeout = 1000; handler.msgbox_retry = function(type, title, text, link, hasRetry) { handler.msgbox(type, title, text, link, hasRetry); if (hasRetry) { self.timer(0, retryConnect); self.timer(reconnectTimeout, retryConnect); reconnectTimeout *= 2; } else { reconnectTimeout = 1000; } } function retryConnect(cancelTimer=false) { if (cancelTimer) self.timer(0, retryConnect); if (!is_port_forward) connecting(); handler.reconnect(); } /******************** end of msgbox ****************************************/ function Progress() { var _val; var pos = -0.25; function step() { if( _val !== undefined ) { this.refresh(); return false; } pos += 0.02; if( pos > 1.25) pos = -0.25; this.refresh(); return true; } function paintNoValue(gfx) { var (w,h) = this.box(#dimension,#inner); var x = pos * w; w = w * 0.25; gfx.fillColor( this.style#color ) .pushLayer(#inner-box) .rectangle(x,0,w,h) .popLayer(); return true; } this[#value] = property(v) { get return _val; set { _val = undefined; pos = -0.25; this.paintContent = paintNoValue; this.animate(step); this.refresh(); } } this.value = ""; } var svg_eye_cross = ; class PasswordComponent: Reactor.Component { this var visible = false; this var value = ''; this var name = 'password'; function this(params) { if (params && params.value) { this.value = params.value; } if (params && params.name) { this.name = params.name; } } function render() { return
{this.visible ? svg_eye_cross : svg_eye}
; } event click $(svg) { var el = this.$(input); var value = el.value; var start = el.xcall(#selectionStart) || 0; var end = el.xcall(#selectionEnd); this.update({ visible: !this.visible }); var me = this; self.timer(30ms, function() { var el = me.$(input); view.focus = el; el.value = value; el.xcall(#setSelection, start, end); }); } } // type: #post, #get, #delete, #put function httpRequest(url, type, params, _onSuccess, _onError, headers="") { if (type != #post) { stderr.println("only post ok"); } handler.post_request(url, JSON.stringify(params), headers); function check_status() { var status = handler.get_async_job_status(); if (status == " ") self.timer(0.1s, check_status); else { try { var data = JSON.parse(status); _onSuccess(data); } catch (e) { _onError(status, 0); } } } check_status(); } function isReasonableSize(r) { var x = r[0]; var y = r[1]; var n = scaleIt(3200); return !(x < -n || x > n || y < -n || y > n); } function awake() { view.windowState = View.WINDOW_SHOWN; view.focus = self; }