view.windowFrame = is_osx ? #extended : #solid; var body; var connections = []; var show_chat = false; var show_elevation = true; var svg_elevate = ; class Body: Reactor.Component { this var cur = 0; function this() { body = this; } function render() { if (connections.length == 0) return
Waiting for new connection ...
; var c = connections[this.cur]; this.connection = c; this.cid = c.id; var auth = c.authorized; var me = this; var callback = function(msg) { me.sendMsg(msg); }; var right_style = show_chat ? "" : "display: none"; var disconnected = c.disconnected; var show_elevation_btn = handler.can_elevate() && show_elevation && !c.is_file_transfer && c.port_forward.length == 0; var show_accept_btn = handler.get_option('approve-mode') != 'password'; // below size:* is a workaround for Linux, it already set in css, but not work, shit sciter return
{c.name[0].toUpperCase()}
{c.name}
({c.peer_id})
{auth ? {disconnected ? translate('Disconnected') : translate('Connected')}{" "}{getElaspsed(c.time, c.now)} : {translate('Request access to your device')}{"..."}}
{c.is_file_transfer || c.port_forward || disconnected ? "" :
{translate('Permissions')}
} {c.is_file_transfer || c.port_forward || disconnected ? "" :
} {c.port_forward ?
Port Forwarding: {c.port_forward}
: ""}
{!auth && !disconnected && show_elevation_btn && show_accept_btn ? : "" } {auth && !disconnected && show_elevation_btn ? : "" }
{!auth && show_accept_btn ? : "" } {!auth ? : "" }
{auth && !disconnected ? : "" } {auth && disconnected ? : "" }
{c.is_file_transfer || c.port_forward ? "" :
{svg_chat}
}
{c.is_file_transfer || c.port_forward ? "" : }
; } function sendMsg(text) { if (!text) return; var { cid, connection } = this; checkClickTime(function() { connection.msgs.push({ name: "me", text: text, time: getNowStr()}); handler.send_msg(cid, text); body.update(); }); } event click $(icon.keyboard) (e) { var { cid, connection } = this; checkClickTime(function() { connection.keyboard = !connection.keyboard; body.update(); handler.switch_permission(cid, "keyboard", connection.keyboard); }); } event click $(icon.clipboard) { var { cid, connection } = this; checkClickTime(function() { connection.clipboard = !connection.clipboard; body.update(); handler.switch_permission(cid, "clipboard", connection.clipboard); }); } event click $(icon.audio) { var { cid, connection } = this; checkClickTime(function() { connection.audio = !connection.audio; body.update(); handler.switch_permission(cid, "audio", connection.audio); }); } event click $(icon.file) { var { cid, connection } = this; checkClickTime(function() { connection.file = !connection.file; body.update(); handler.switch_permission(cid, "file", connection.file); }); } event click $(icon.restart) { var { cid, connection } = this; checkClickTime(function() { connection.restart = !connection.restart; body.update(); handler.switch_permission(cid, "restart", connection.restart); }); } event click $(icon.recording) { var { cid, connection } = this; checkClickTime(function() { connection.recording = !connection.recording; body.update(); handler.switch_permission(cid, "recording", connection.recording); }); } event click $(button#accept) { var { cid, connection } = this; checkClickTime(function() { connection.authorized = true; body.update(); handler.authorize(cid); self.timer(30ms, function() { view.windowState = View.WINDOW_MINIMIZED; }); }); } event click $(button#elevate_accept) { var { cid, connection } = this; checkClickTime(function() { connection.authorized = true; show_elevation = false; body.update(); handler.elevate_portable(cid); handler.authorize(cid); self.timer(30ms, function() { view.windowState = View.WINDOW_MINIMIZED; }); }); } event click $(button#elevate) { var { cid, connection } = this; checkClickTime(function() { show_elevation = false; body.update(); handler.elevate_portable(cid); self.timer(30ms, function() { view.windowState = View.WINDOW_MINIMIZED; }); }); } event click $(button#dismiss) { var cid = this.cid; checkClickTime(function() { handler.close(cid); }); } event click $(button#disconnect) { var cid = this.cid; checkClickTime(function() { handler.close(cid); }); } event click $(button#close) { var cid = this.cid; if (this.cur >= 0 && this.cur < connections.length){ handler.remove_disconnected_connection(cid); connections.splice(this.cur, 1); if (connections.length > 0) { if (this.cur > 0) this.cur -= 1; else this.cur = connections.length - 1; header.update(); body.update(); } else { handler.quit(); } } } } $(body).content(); var header; class Header: Reactor.Component { function this() { header = this; } function render() { var me = this; var conn = connections[body.cur]; if (conn && conn.unreaded > 0) {; var el = me.select("#unreaded" + conn.id); if (el) el.style.set { display: "inline-block", }; self.timer(300ms, function() { conn.unreaded = 0; var el = me.select("#unreaded" + conn.id); if (el) el.style.set { display: "none", }; }); } var tabs = connections.map(function(c, i) { return me.renderTab(c, i) }); return
{tabs}
< >
; } function renderTab(c, i) { var cur = body.cur; return
{c.name} {c.unreaded > 0 ? {c.unreaded} : ""}
; } function update_cur(idx) { checkClickTime(function() { body.cur = idx; update(); self.timer(1ms, adjustHeader); }); } event click $(div.tab) (_, me) { var idx = me.index; if (idx == body.cur) return; this.update_cur(idx); } event click $(span#left-arrow) { var cur = body.cur; if (cur == 0) return; this.update_cur(cur - 1); } event click $(span#right-arrow) { var cur = body.cur; if (cur == connections.length - 1) return; this.update_cur(cur + 1); } } if (is_osx) { $(header).content(
); $(header).attributes["role"] = "window-caption"; } else { $(div.window-toolbar).content(
); setWindowButontsAndIcon(true); } event click $(div.chaticon) { checkClickTime(function() { show_chat = !show_chat; adaptSizeForChat(); if (show_chat) { view.focus = $(.outline-focus); } }); } function checkClickTime(callback) { var click_callback_time = getTime(); handler.check_click_time(body.cid); self.timer(120ms, function() { var d = click_callback_time - handler.get_click_time(); if (d > 120) callback(); }); } function adaptSizeForChat() { $(div.right-panel).style.set { display: show_chat ? "block" : "none", }; var (x, y, w, h) = view.box(#rectw, #border, #screen); if (show_chat && w < scaleIt(600)) { view.move(x - (scaleIt(600) - w), y, scaleIt(600), h); } else if (!show_chat && w > scaleIt(450)) { view.move(x + (w - scaleIt(300)), y, scaleIt(300), h); } } function update() { header.update(); body.update(); } function bring_to_top(idx=-1) { if (view.windowState == View.WINDOW_HIDDEN || view.windowState == View.WINDOW_MINIMIZED) { if (is_linux) { view.focus = self; } else { view.windowState = View.WINDOW_SHOWN; } if (idx >= 0) body.cur = idx; } else { view.windowTopmost = true; view.windowTopmost = false; } } handler.addConnection = function(id, is_file_transfer, port_forward, peer_id, name, authorized, keyboard, clipboard, audio, file, restart, recording) { stdout.println("new connection #" + id + ": " + peer_id); var conn; connections.map(function(c) { if (c.id == id) conn = c; }); if (conn) { conn.authorized = authorized; update(); return; } var idx = -1; connections.map(function(c, i) { if (c.disconnected && c.peer_id == peer_id) idx = i; }); if (!name) name = "NA"; conn = { id: id, is_file_transfer: is_file_transfer, peer_id: peer_id, port_forward: port_forward, name: name, authorized: authorized, time: new Date(), now: new Date(), keyboard: keyboard, clipboard: clipboard, msgs: [], unreaded: 0, audio: audio, file: file, restart: restart, recording: recording, disconnected: false }; if (idx < 0) { connections.push(conn); body.cur = connections.length - 1; } else { connections[idx] = conn; body.cur = idx; } bring_to_top(); update(); self.timer(1ms, adjustHeader); if (authorized) { self.timer(3s, function() { view.windowState = View.WINDOW_MINIMIZED; }); } } handler.removeConnection = function(id, close) { var i = -1; connections.map(function(c, idx) { if (c.id == id) i = idx; }); if (i < 0) return; if (close) { connections.splice(i, 1); } else { var conn = connections[i]; conn.disconnected = true; } if (connections.length > 0) { if (body.cur >= i && body.cur > 0 && close) body.cur -= 1; update(); } } handler.newMessage = function(id, text) { var idx = -1; connections.map(function(c, i) { if (c.id == id) idx = i; }); var conn = connections[idx]; if (!conn) return; conn.msgs.push({name: conn.name, text: text, time: getNowStr()}); bring_to_top(idx); if (idx == body.cur) { var shouldAdapt = !show_chat; show_chat = true; if (shouldAdapt) adaptSizeForChat(); } conn.unreaded += 1; update(); } handler.showElevation = function(show) { if (show != show_elevation) { show_elevation = show; update(); } } view << event statechange { adjustBorder(); } function self.ready() { adjustBorder(); var (sw, sh) = view.screenBox(#workarea, #dimension); var w = scaleIt(300); var h = scaleIt(400); view.move(sw - w, 0, w, h); } function getElaspsed(time, now) { var seconds = Date.diff(time, now, #seconds); var hours = seconds / 3600; var days = hours / 24; hours = hours % 24; var minutes = seconds % 3600 / 60; seconds = seconds % 60; var out = String.printf("%02d:%02d:%02d", hours, minutes, seconds); if (days > 0) { out = String.printf("%d day%s %s", days, days > 1 ? "s" : "", out); } return out; } var ui_status_cache = [""]; function check_update_ui() { self.timer(1s, function() { var approve_mode = handler.get_option('approve-mode'); var changed = false; if (ui_status_cache[0] != approve_mode) { ui_status_cache[0] = approve_mode; changed = true; } if (changed) update(); check_update_ui(); }); } check_update_ui(); function updateTime() { self.timer(1s, function() { var now = new Date(); connections.map(function(c) { if (!c.authorized) c.time = now; if (!c.disconnected) c.now = now; }); var el = $(#time); if (el) { var c = connections[body.cur]; if (c && c.authorized && !c.disconnected) { el.text = getElaspsed(c.time, c.now); } } updateTime(); }); } updateTime(); var tm0 = getTime(); function self.closing() { if (connections.length == 0 && getTime() - tm0 > 30000) return true; view.windowState = View.WINDOW_HIDDEN; return false; } function adjustHeader() { var hw = $(header).box(#width) / scaleFactor; var tabswrapper = $(div.tabs-wrapper); var tabs = $(div.tabs); var arrows = $(div.tab-arrows); if (!arrows) return; var n = connections.length; var wtab = 80; var max = hw - 98; var need_width = n * wtab + scaleIt(2); // include border of active tab if (need_width < max) { arrows.style.set { display: "none", }; tabs.style.set { width: need_width, margin-left: 0, }; tabswrapper.style.set { width: need_width, }; } else { var margin = (body.cur + 1) * wtab - max + 30; if (margin < 0) margin = 0; arrows.style.set { display: "block", }; tabs.style.set { width: (max - 20 + margin) + 'px', margin-left: -margin + 'px' }; tabswrapper.style.set { width: (max + 10) + 'px', }; } } view.on("size", adjustHeader); // handler.addConnection(0, false, 0, "", "test1", true, false, false, true, true); // handler.addConnection(1, false, 0, "", "test2--------", true, false, false, false, false); // handler.addConnection(2, false, 0, "", "test3", true, false, false, false, false); // handler.newMessage(0, 'h');