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 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 ;
}
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 = ;
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 (evt.keyCode == Event.VK_ENTER ||
(view.mediaVar("platform") == "OSX" && evt.keyCode == 0x4C)) {
this.send();
}
}
}
event click $(div.send span) {
this.send();
view.focus = $(input);
}
}
/******************** end of chatbox ****************************************/
/******************** start of msgbox ****************************************/
var remember_password = false;
var msgbox_params;
function getMsgboxParams() {
return msgbox_params;
}
// tmp workaround https://sciter.com/forums/topic/menu-not-be-hidden-when-open-dialog-on-linux/
function msgbox(type, title, text, callback=null, height=180, width=500, retry=0, contentStyle="") {
if (is_linux) { // fix menu not hidden issue
self.timer(1ms,
function() {
msgbox_(type, title, text, callback, height, width, retry, contentStyle);
});
} else {
msgbox_(type, title, text, callback, height, width, retry, contentStyle);
}
}
function msgbox_(type, title, text, callback, height, width, retry, contentStyle) {
var has_msgbox = msgbox_params != null;
if (!has_msgbox && !type) return;
var remember = false;
try {
remember = handler.get_remember();
} catch(e) {}
msgbox_params = {
remember: remember, type: type, text: text, title: title,
getParams: getMsgboxParams,
callback: callback, translate: translate,
retry: retry, contentStyle: contentStyle,
};
if (has_msgbox) return;
var dialog = {
client: true,
parameters: msgbox_params,
width: width + (is_xfce ? 50 : 0),
height: height + (is_xfce ? 50 : 0),
};
var html = handler.get_msgbox();
if (html) dialog.html = html;
else dialog.url = self.url("msgbox.html");
var res = view.dialog(dialog);
msgbox_params = null;
stdout.printf("msgbox return, type: %s, res: %s\n", type, res);
if (type.indexOf("custom") >= 0) {
//
} else if (!res) {
if (!is_port_forward) view.close();
} else if (res == "!alive") {
// do nothing
} else if (res.type == "input-password") {
handler.login(res.password, res.remember);
if (!is_port_forward) msgbox("connecting", "Connecting...", "Logging in...");
} else if (res.reconnect) {
if (!is_port_forward) connecting();
handler.reconnect();
}
}
function connecting() {
handler.msgbox("connecting", "Connecting...", "Connection in progress. Please wait.");
}
handler.msgbox = function(type, title, text, retry=0) {
self.timer(30ms, function() { msgbox(type, title, text, null, 180, 500, retry); });
}
var reconnectTimeout = 1;
handler.msgbox_retry = function(type, title, text, hasRetry) {
handler.msgbox(type, title, text, hasRetry ? reconnectTimeout : 0);
if (hasRetry) {
reconnectTimeout *= 2;
} else {
reconnectTimeout = 1;
}
}
/******************** 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);
});
}
}
function isReasonableSize(r) {
var x = r[0];
var y = r[1];
return !(x < -3200 || x > 3200 || y < -3200 || y > 3200);
}