import { is_osx,view,OS,handler,translate,msgbox,is_win,svg_checkmark,svg_edit,isReasonableSize,centerize,svg_eye } from "./common";
import { SearchBar,SessionStyle,SessionList } from "./ab.js";
import {$} from "@sciter"; //TEST $$ import
if (is_osx) view.blurBehind = "light";
console.log("current platform:", OS);
console.log("wayland",handler.xcall("is_login_wayland"));
// html min-width, min-height not working on mac, below works for all
view.minSize = [500, 300]; // TODO not work on ubuntu
export var app; // 注意判空
var tmp = handler.xcall("get_connect_status");
var connect_status = tmp[0];
var service_stopped = false;
var software_update_url = "";
var key_confirmed = tmp[1];
var system_error = "";
export const svg_menu = ;
var my_id = "";
function get_id() {
my_id = handler.xcall("get_id");
return my_id;
}
class ConnectStatus extends Element {
render() {
return(
);
}
getConnectStatusStr() {
if (service_stopped) {
return translate("Service is not running");
} else if (connect_status == -1) {
return translate('not_ready_status');
} else if (connect_status == 0) {
return translate('connecting_status');
}
return translate("Ready");
}
["on click at #start-service"]() {
handler.xcall("set_option","stop-service", "");
}
}
class RecentSessions extends Element {
sessionList;
componentDidMount(){
this.sessionList = this.$("#SessionList")
}
render() {
let sessions = handler.xcall("get_recent_sessions");
if (sessions.length == 0) return ;
return (
{translate("Recent Sessions")}
{!app.hidden && }
{!app.hidden && }
{!app.hidden && }
);
}
filter(v) {
this.sessionList.filter(v);
}
}
export function createNewConnect(id, type) {
id = id.replace(/\s/g, "");
app.remote_id.value = formatId(id);
if (!id) return;
if (id == my_id) {
msgbox("custom-error", "Error", "You cannot connect to your own computer");
return;
}
handler.xcall("set_remote_id",id);
handler.xcall("new_remote",id, type);
}
var direct_server;
class DirectServer: Reactor.Component {
function this() {
direct_server = this;
}
function render() {
var text = translate("Enable Direct IP Access");
var cls = handler.get_option("direct-server") == "Y" ? "selected" : "line-through";
return
{svg_checkmark}{text}
;
}
function onClick() {
handler.set_option("direct-server", handler.get_option("direct-server") == "Y" ? "" : "Y");
this.update();
}
}
var myIdMenu;
var audioInputMenu;
class AudioInputs extends Element {
this() {
audioInputMenu = this;
}
render() {
// TODO this.show
if (!this.show) return ;
let inputs = handler.xcall("get_sound_inputs");
if (is_win) inputs = ["System Sound"].concat(inputs);
if (!inputs.length) return ;
inputs = ["Mute"].concat(inputs);
setTimeout(()=>this.toggleMenuState(),1);
return (
{translate('Audio Input')}
);
}
get_default() {
if (is_win) return "System Sound";
return "";
}
get_value() {
return handler.xcall("get_option","audio-input") || this.get_default();
}
toggleMenuState() {
let v = this.get_value();
for (let el of this.$$("menu#audio-input>li")) {
let selected = el.id == v;
el.classList.toggle("selected", selected);
}
}
["on click at menu#audio-input>li"](_, me) {
let v = me.id;
if (v == this.get_value()) return;
if (v == this.get_default()) v = "";
handler.xcall("set_option","audio-input", v);
this.toggleMenuState();
}
}
class MyIdMenu extends Element {
this() {
myIdMenu = this;
}
render() {
return (
{this.renderPop()}
ID{svg_menu}
);
}
renderPop() {
return ();
}
// TEST svg#menu // .popup()
["on click at svg#menu"](_, me) {
console.log("open menu")
audioInputMenu.componentUpdate({ show: true });
this.toggleMenuState();
let menu = this.$("menu#config-options");
me.popup(menu);
}
toggleMenuState() {
for (let el of this.$$("menu#config-options>li")) {
if (el.id && el.id.indexOf("enable-") == 0) {
let enabled = handler.xcall("get_option",el.id) != "N";
console.log(el.id,enabled)
el.classList.toggle("selected", enabled);
el.classList.toggle("line-through", !enabled);
}
}
}
["on click at menu#config-options>li"] (_, me) {
if (me.id && me.id.indexOf("enable-") == 0) {
handler.xcall("set_option",me.id, handler.xcall("get_option",me.id) == "N" ? "" : "N");
}
if (me.id == "whitelist") {
let old_value = handler.xcall("get_option","whitelist").split(",").join("\n");
msgbox("custom-whitelist", translate("IP Whitelisting"), "
\
" + translate("whitelist_sep") + "
\
\
\
",
function(res=null) {
if (!res) return;
let value = (res.text || "").trim();
if (value) {
let values = value.split(/[\s,;\n]+/g);
for (let ip in values) {
if (!ip.match(/^\d+\.\d+\.\d+\.\d+$/)) {
return translate("Invalid IP") + ": " + ip;
}
}
value = values.join("\n");
}
if (value == old_value) return;
console.log("whitelist updated");
handler.xcall("set_option","whitelist", value.replace("\n", ","));
}, 300);
} else if (me.id == "custom-server") {
let configOptions = handler.xcall("get_options");
let old_relay = configOptions["relay-server"] || "";
let old_id = configOptions["custom-rendezvous-server"] || "";
msgbox("custom-server", "ID/Relay Server", "
\
" + translate("ID Server") + ":
\
" + translate("Relay Server") + ":
\
\
",
function(res=null) {
if (!res) return;
let id = (res.id || "").trim();
let relay = (res.relay || "").trim();
if (id == old_id && relay == old_relay) return;
if (id) {
let err = handler.xcall("test_if_valid_server",id);
if (err) return translate("ID Server") + ": " + err;
}
if (relay) {
let err = handler.xcall("test_if_valid_server",relay);
if (err) return translate("Relay Server") + ": " + err;
}
configOptions["custom-rendezvous-server"] = id;
configOptions["relay-server"] = relay;
handler.xcall("set_options",configOptions);
}, 240);
} else if (me.id == "socks5-server") {
var socks5 = handler.get_socks() || {};
var old_proxy = socks5[0] || "";
var old_username = socks5[1] || "";
var old_password = socks5[2] || "";
msgbox("custom-server", "Socks5 Proxy",
{translate("Hostname")}
{translate("Username")}
{translate("Password")}
, function(res=null) {
if (!res) return;
var proxy = (res.proxy || "").trim();
var username = (res.username || "").trim();
var password = (res.password || "").trim();
if (proxy == old_proxy && username == old_username && password == old_password) return;
if (proxy) {
var err = handler.test_if_valid_server(proxy);
if (err) return translate("Server") + ": " + err;
}
handler.set_socks(proxy, username, password);
}, 240);
} else if (me.id == "stop-service") {
handler.xcall("set_option","stop-service", service_stopped ? "" : "Y");
} else if (me.id == "about") {
let name = handler.xcall("get_app_name");
msgbox("custom-nocancel-nook-hasclose", "About " + name, "
);
}
["on click at button#connect"](){
this.newRemote("connect");
}
["on click at button#file-transfer"]() {
this.newRemote("file-transfer");
}
["on keydown"](evt) {
if (!evt.shortcutKey) {
// TODO TEST Windows/Mac
if (evt.code == "KeyRETURN") {
var el = $("button#connect");
view.focus = el;
el.click();
// simulate button click effect, windows does not have this issue
el.classList.toggle("active", true);
el.timer(300, ()=> el.classList.toggle("active", false));
}
}
}
newRemote(type) {
createNewConnect(this.remote_id.value, type);
}
}
class InstallMe extends Element {
render() {
return (
{translate('install_tip')}
);
}
["on click at #install-me"]() {
handler.xcall("goto_install");
}
}
const http = function() {
function makeRequest(httpverb) {
return function( params ) {
params.type = httpverb;
// TODO request
view.request(params);
};
}
function download(from, to, ...args) {
// TODO #get
let rqp = { type:"get", url: from, toFile: to };
let fn = 0;
let on = 0;
// TODO p in / p of?
for( let p in args )
if( p instanceof Function )
{
switch(++fn) {
case 1: rqp.success = p; break;
case 2: rqp.error = p; break;
case 3: rqp.progress = p; break;
}
} else if( p instanceof Object )
{
switch(++on) {
case 1: rqp.params = p; break;
case 2: rqp.headers = p; break;
}
}
// TODO request
view.request(rqp);
}
return {
get: makeRequest("get"),
post: makeRequest("post"),
put: makeRequest("put"),
del: makeRequest("delete"),
download: download
};
}();
class UpgradeMe extends Element {
render() {
let update_or_download = is_osx ? "download" : "update";
return (
{translate('Status')}
{translate('Your installation is lower version.')}
{translate('Click to upgrade')}
);
}
["on click at #install-me"]() {
handler.xcall("update_me");
}
}
class UpdateMe extends Element {
render() {
let update_or_download = "download"; // !is_win ? "download" : "update";
return (
{translate('Status')}
There is a newer version of {handler.xcall("get_app_name")} ({handler.xcall("get_new_version")}) available.
Click to {update_or_download}
);
}
["on click at #install-me"]() {
handler.xcall("open_url","https://rustdesk.com");
return;
// TODO return?
if (!is_win) {
handler.xcall("open_url","https://rustdesk.com");
return;
}
let url = software_update_url + '.' + handler.xcall("get_software_ext");
let path = handler.xcall("get_software_store_path");
let onsuccess = function(md5) {
this.$("#download-percent").content(translate("Installing ..."));
handler.xcall("update_me",path);
};
let onerror = function(err) {
msgbox("custom-error", "Download Error", "Failed to download");
};
let onprogress = function(loaded, total) {
if (!total) total = 5 * 1024 * 1024;
let el = this.$("#download-percent");
el.style.setProperty("display","block");
el.content("Downloading %" + (loaded * 100 / total));
};
console.log("Downloading " + url + " to " + path);
http.download(
url,
document.url(path),
onsuccess, onerror, onprogress);
}
}
class SystemError extends Element {
render() {
return (
{system_error}
);
}
}
class TrustMe extends Element {
render() {
return (
{translate('Configuration Permissions')}
{translate('config_acc')}
{translate('Configure')}
);
}
["on click at #trust-me"] () {
handler.xcall("is_process_trusted",true);
watch_trust();
}
}
class CanScreenRecording extends Element {
render() {
return (
{translate('Configuration Permissions')}
{translate('config_screen')}
{translate('Configure')}
);
}
["on click at #screen-recording"]() {
handler.xcall("is_can_screen_recording",true);
watch_trust();
}
}
class FixWayland extends Element {
render() {
return (
{translate('Warning')}
{translate('Login screen using Wayland is not supported')}
{translate('Fix it')}
({translate('Reboot required')})
);
}
["on click at #fix-wayland"] () {
handler.xcall("fix_login_wayland");
app.componentUpdate();
}
}
class ModifyDefaultLogin extends Element {
render() {
return (
{translate('Warning')}
{translate('Current Wayland display server is not supported')}
{translate('Fix it')}
({translate('Reboot required')})
);
}
["on click at #modify-default-login"]() {
// TEST change tis old:
// if (var r = handler.modify_default_login()) {
// msgbox("custom-error", "Error", r);
// }
let r = handler.xcall("modify_default_login");
if (r) {
msgbox("custom-error", "Error", r);
}
app.componentUpdate();
}
}
function watch_trust() {
// not use TrustMe::update, because it is buggy
let trusted = handler.xcall("is_process_trusted",false);
let el = document.$("div.trust-me");
if (el) {
el.style.setProperty("display", trusted ? "none" : "block");
}
// if (trusted) return;
// TODO dont have exit?
setTimeout(() => {
watch_trust()
}, 1000);
}
class PasswordEyeArea extends Element {
render() {
return (