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 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 ;
}
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;
}
function msgbox(type, title, text, callback, height, width, retry=0) {
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, retry: retry,
};
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") {
if (!is_port_forward) connecting();
handler.login(res.password, res.remember);
} 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, callback=null, height=180, width=500, retry=0) {
// directly call view.Dialog from native may crash, add timer here, seem safe
// too short time, msgbox won't get focus, per my test, 150 is almost minimun
self.timer(150ms, function() { msgbox(type, title, text, callback, height, width, retry); });
}
var reconnectTimeout = 1;
handler.msgbox_retry = function(type, title, text, hasRetry, callback=null, height=180, width=500) {
handler.msgbox(type, title, text, callback, height, width, 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 = "";
}