const view = Window.this; export const handler = document.$("#handler") || view; try { view.windowIcon = document.url(handler.xcall("get_icon")); } catch (e) { } const OS = view.mediaVar("platform"); const is_osx = OS == "OSX"; const is_win = OS == "Windows"; const is_linux = OS == "Linux"; view.mediaVar("is_osx", is_osx); view.mediaVar("not_osx", !is_osx); var is_file_transfer; var is_xfce = false; try { is_xfce = handler.xcall("is_xfce"); } catch (e) { } export function translate(name) { try { return handler.xcall("t", name); } catch (_) { return name; } } export function hashCode(str) { let hash = 160 << 16 + 114 << 8 + 91; for (let i = 0; i < str.length; i += 1) { hash = str.charCodeAt(i) + ((hash << 5) - hash); } return hash % 16777216; } export function intToRGB(i, a = 1) { return `rgba(${((i >> 16) & 0xFF)}, ${((i >> 8) & 0x7F)},${(i & 0xFF)},${a})`; } export function string2RGB(s, a = 1) { return intToRGB(hashCode(s), a); } export function getTime() { return new Date().valueOf(); } export function platformSvg(platform, color) { platform = (platform || "").toLowerCase(); if (platform == "linux") { return ( ); } if (platform == "mac os") { return ( ); } return ( ); } export function centerize(w, h) { let [sx, sy, sw, sh] = view.screenBox("workarea", "rectw"); if (w > sw) w = sw; if (h > sh) h = sh; const x = (sx + sw - w) / 2; const y = (sy + sh - h) / 2; view.move(x, y, w, h); } // TODO CSS export function setWindowButontsAndIcon(only_min = false) { if (only_min) { document.$("div.window-buttons").content(
); } else { document.$("div.window-buttons").content(
); } document.$("div.window-icon>icon").style.setProperty( "background-image", `url(${handler.xcall("get_icon")})`, ); } export function adjustBorder() { if (is_osx) { let headerStyle = document.$("header").style; if (view.state == Window.WINDOW_FULL_SCREEN) { headerStyle.setProperty("display", "none",); } else { headerStyle.setProperty("display", "block",); headerStyle.setProperty("padding", "0",); } return; } if (view.state == Window.WINDOW_MAXIMIZED) { document.style.setProperty("border", "window-frame-width solid transparent"); } else if (view.state == Window.WINDOW_FULL_SCREEN) { document.style.setProperty("border", "none"); } else { document.style.setProperty("border", "black solid 1px"); } let el = document.$("button#maximize"); if (el) el.classList.toggle("restore", view.state == Window.WINDOW_MAXIMIZED); el = document.$("span#fullscreen"); if (el) el.classList.toggle("active", view.state == Window.WINDOW_FULL_SCREEN); } export const svg_checkmark = (); export const svg_edit = ( ); export const svg_eye = ( ); export const svg_send = ( ); export const svg_chat = ( ); export function scrollToBottom(el) { // TODO .box() let y = el.box(#height, #content) - el.box(#height, #client); el.scrollTo(0, y); } export function getNowStr() { let now = new Date(); return String.printf("%02d:%02d:%02d", now.hour, now.minute, now.second); } /******************** start of chatbox ****************************************/ export class ChatBox extends Element { msgs = []; callback; constructor(props) { if (props) { this.msgs = props.msgs || []; this.callback = props.callback; } } renderMsg(msg) { let cls = msg.name == "me" ? "right-side msg" : "left-side msg"; return (
{msg.name == "me" ?
{msg.time + " "} me
:
{msg.name} {" " + msg.time}
}
{msg.text}
); } render() { let msgs = this.msgs.map((msg) => this.renderMsg(msg)); setTimeout(() => { scrollToBottom(this.msgs); }, 1); // TODO @{this.msgs} in TIS: return (
{msgs}
{svg_send}
); } send() { let el = this.$("input"); let value = (el.value || "").trim(); el.value = ""; if (!value) return; if (this.callback) this.callback(value); } ["on keydown at input"](evt) { // TODO is shortcutKey useless? if (!evt.shortcutKey) { // TODO TEST Windows/Mac if (evt.code == "KeyRETURN") { this.send(); } } } ["on click at div.send span"](evt) { this.send(); view.focus = this.$("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/ export function msgbox(type, title, text, callback = null, height = 180, width = 500, retry = 0, contentStyle = "") { if (is_linux) { // fix menu not hidden issue setTimeout(() => msgbox_(type, title, text, callback, height, width, retry, contentStyle), 1); } else { msgbox_(type, title, text, callback, height, width, retry, contentStyle); } } function msgbox_(type, title, text, callback, height, width, retry, contentStyle) { let has_msgbox = msgbox_params != null; if (!has_msgbox && !type) return; let remember = false; try { remember = handler.xcall("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; let dialog = { client: true, parameters: msgbox_params, width: width + (is_xfce ? 50 : 0), height: height + (is_xfce ? 50 : 0), }; let html = handler.xcall("get_msgbox"); if (html) dialog.html = html; else dialog.url = document.url("msgbox.html"); let res = view.modal(dialog); msgbox_params = null; console.log(`msgbox return, type: ${type}, res: ${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) { setTimeout(() => msgbox(type, title, text, null, 180, 500, retry), 30); } 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 ****************************************/ // TODO Progress // 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 = ""; // } const svg_eye_cross = ( ); export class PasswordComponent extends Element { visible = false; value = ''; name = 'password'; constructor(props) { if (props && props.value) { this.value = props.value; } if (props && props.name) { this.name = props.name; } } render() { return (
{this.visible ? svg_eye_cross : svg_eye}
); } ["on click at svg"](svg) { let el = this.$("input"); let value = el.value; // TODO selectionStart/selectionEnd run ok,but always return 0 let start = el.xcall("selectionStart") || 0; let end = el.xcall("selectionEnd"); this.componentUpdate({ visible: !this.visible }); setTimeout(() => { let el = this.$("input"); view.focus = el; el.value = value; el.xcall("setSelection", start, end); }, 30) } } export function isReasonableSize(r) { let x = r[0]; let y = r[1]; return !(x < -3200 || x > 3200 || y < -3200 || y > 3200); }