first step to js
This commit is contained in:
parent
7dadf3da7a
commit
2a18d7f77d
@ -1,5 +1,5 @@
|
||||
import { handler,view,is_osx,string2RGB,adjustBorder,svg_chat,translate,ChatBox,getNowStr,setWindowButontsAndIcon,is_linux } from "./common.js";
|
||||
import {$,$$} from "@sciter";
|
||||
import {$} from "@sciter";
|
||||
// TODO in sciterjs window-frame
|
||||
// view.windowFrame = is_osx ? #extended : #solid;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
export const view = Window.this;
|
||||
export const handler = document.$("#handler") || view;
|
||||
|
||||
@ -10,8 +11,8 @@ export 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;
|
||||
export var is_file_transfer;
|
||||
export var is_xfce = false;
|
||||
try { is_xfce = handler.xcall("is_xfce"); } catch (e) { }
|
||||
|
||||
|
||||
@ -266,7 +267,7 @@ function msgbox_(type, title, text, callback, height, width, retry, contentStyle
|
||||
}
|
||||
}
|
||||
|
||||
function connecting() {
|
||||
export function connecting() {
|
||||
handler.msgbox("connecting", "Connecting...", "Connection in progress. Please wait.");
|
||||
}
|
||||
|
||||
|
@ -1,30 +1,34 @@
|
||||
import { handler,svg_send,translate,msgbox } from "./common.js";
|
||||
import {$} from "@sciter";
|
||||
|
||||
var remote_home_dir;
|
||||
|
||||
var svg_add_folder = <svg viewBox="0 0 443.29 443.29">
|
||||
const svg_add_folder = (<svg viewBox="0 0 443.29 443.29">
|
||||
<path d="m277.06 332.47h27.706v-55.412h55.412v-27.706h-55.412v-55.412h-27.706v55.412h-55.412v27.706h55.412z"/>
|
||||
<path d="m415.59 83.118h-202.06l-51.353-51.353c-2.597-2.597-6.115-4.058-9.794-4.058h-124.68c-15.274-1e-3 -27.706 12.431-27.706 27.705v332.47c0 15.273 12.432 27.706 27.706 27.706h387.88c15.273 0 27.706-12.432 27.706-27.706v-277.06c0-15.274-12.432-27.706-27.706-27.706zm0 304.76h-387.88v-332.47h118.94l51.354 51.353c2.597 2.597 6.115 4.058 9.794 4.058h207.79z"/>
|
||||
</svg>;
|
||||
var svg_trash = <svg viewBox="0 0 473.41 473.41">
|
||||
</svg>);
|
||||
const svg_trash = (<svg viewBox="0 0 473.41 473.41">
|
||||
<path d="m443.82 88.765h-88.765v-73.971c0-8.177-6.617-14.794-14.794-14.794h-207.12c-8.177 0-14.794 6.617-14.794 14.794v73.971h-88.764v29.588h14.39l57.116 342.69c1.185 7.137 7.354 12.367 14.592 12.367h241.64c7.238 0 13.407-5.23 14.592-12.367l57.116-342.69h14.794c-1e-3 0-1e-3 -29.588-1e-3 -29.588zm-295.88-59.177h177.53v59.176h-177.53zm196.85 414.24h-216.58l-54.241-325.47h325.06z"/>
|
||||
<path transform="matrix(.064 -.998 .998 .064 -.546 19.418)" d="m-360.4 301.29h207.54v29.592h-207.54z"/>
|
||||
<path transform="matrix(.998 -.064 .064 .998 -.628 .399)" d="m141.64 202.35h29.592v207.54h-29.592z"/>
|
||||
</svg>;
|
||||
var svg_arrow = <svg viewBox="0 0 482.24 482.24">
|
||||
</svg>);
|
||||
const svg_arrow = (<svg viewBox="0 0 482.24 482.24">
|
||||
<path d="m206.81 447.79-206.81-206.67 206.74-206.67 24.353 24.284-165.17 165.17h416.31v34.445h-416.31l165.24 165.24z"/>
|
||||
</svg>;
|
||||
var svg_home = <svg viewBox="0 0 476.91 476.91">
|
||||
</svg>);
|
||||
const svg_home = (<svg viewBox="0 0 476.91 476.91">
|
||||
<path d="m461.78 209.41-212.21-204.89c-6.182-6.026-16.042-6.026-22.224 0l-212.2 204.88c-3.124 3.015-4.888 7.17-4.888 11.512 0 8.837 7.164 16 16 16h28.2v224c0 8.837 7.163 16 16 16h112c8.837 0 16-7.163 16-16v-128h80v128c0 8.837 7.163 16 16 16h112c8.837 0 16-7.163 16-16v-224h28.2c4.338 0 8.489-1.761 11.504-4.88 6.141-6.354 5.969-16.483-0.384-22.624zm-39.32 11.504c-8.837 0-16 7.163-16 16v224h-112v-128c0-8.837-7.163-16-16-16h-80c-8.837 0-16 7.163-16 16v128h-112v-224c0-8.837-7.163-16-16-16h-28.2l212.2-204.88 212.28 204.88h-28.28z"/>
|
||||
</svg>;
|
||||
var svg_refresh = <svg viewBox="0 0 551.13 551.13">
|
||||
</svg>);
|
||||
const svg_refresh = (<svg viewBox="0 0 551.13 551.13">
|
||||
<path d="m482.24 310.01c0 113.97-92.707 206.67-206.67 206.67s-206.67-92.708-206.67-206.67c0-102.21 74.639-187.09 172.23-203.56v65.78l86.114-86.114-86.114-86.115v71.641c-116.65 16.802-206.67 117.14-206.67 238.37 0 132.96 108.16 241.12 241.12 241.12s241.12-108.16 241.12-241.12z"/>
|
||||
</svg>;
|
||||
var svg_cancel = <svg .cancel viewBox="0 0 612 612"><polygon points="612 36.004 576.52 0.603 306 270.61 35.478 0.603 0 36.004 270.52 306.01 0 576 35.478 611.4 306 341.41 576.52 611.4 612 576 341.46 306.01"/></svg>;
|
||||
var svg_computer = <svg .computer viewBox="0 0 480 480">
|
||||
</svg>);
|
||||
const svg_cancel = (<svg class="cancel" viewBox="0 0 612 612"><polygon points="612 36.004 576.52 0.603 306 270.61 35.478 0.603 0 36.004 270.52 306.01 0 576 35.478 611.4 306 341.41 576.52 611.4 612 576 341.46 306.01"/></svg>);
|
||||
const svg_computer = (<svg class="computer" viewBox="0 0 480 480">
|
||||
<g>
|
||||
<path fill="#2C8CFF" d="m276 395v11.148c0 2.327-1.978 4.15-4.299 3.985-21.145-1.506-42.392-1.509-63.401-0.011-2.322 0.166-4.3-1.657-4.3-3.985v-11.137c0-2.209 1.791-4 4-4h64c2.209 0 4 1.791 4 4zm204-340v288c0 17.65-14.35 32-32 32h-416c-17.65 0-32-14.35-32-32v-288c0-17.65 14.35-32 32-32h416c17.65 0 32 14.35 32 32zm-125.62 386.36c-70.231-21.843-158.71-21.784-228.76 0-4.22 1.31-6.57 5.8-5.26 10.02 1.278 4.085 5.639 6.591 10.02 5.26 66.093-20.58 151.37-21.125 219.24 0 4.22 1.31 8.71-1.04 10.02-5.26s-1.04-8.71-5.26-10.02z"/>
|
||||
</g>
|
||||
</svg>;
|
||||
</svg>);
|
||||
|
||||
// TODO
|
||||
function getSize(type, size) {
|
||||
if (!size) {
|
||||
if (type <= 3) return "";
|
||||
@ -47,15 +51,15 @@ function getSize(type, size) {
|
||||
}
|
||||
|
||||
function getParentPath(is_remote, path) {
|
||||
var sep = handler.get_path_sep(is_remote);
|
||||
var res = path.lastIndexOf(sep);
|
||||
let sep = handler.xcall("get_path_sep",is_remote);
|
||||
let res = path.lastIndexOf(sep);
|
||||
if (res <= 0) return "/";
|
||||
return path.substr(0, res);
|
||||
}
|
||||
|
||||
function getFileName(is_remote, path) {
|
||||
var sep = handler.get_path_sep(is_remote);
|
||||
var res = path.lastIndexOf(sep);
|
||||
let sep = handler.xcall("get_path_sep",is_remote);
|
||||
let res = path.lastIndexOf(sep);
|
||||
return path.substr(res + 1);
|
||||
}
|
||||
|
||||
@ -63,76 +67,75 @@ function getExt(name) {
|
||||
if (name.indexOf(".") == 0) {
|
||||
return "";
|
||||
}
|
||||
var i = name.lastIndexOf(".");
|
||||
let i = name.lastIndexOf(".");
|
||||
if (i > 0) return name.substr(i + 1);
|
||||
return "";
|
||||
}
|
||||
|
||||
var jobIdCounter = 1;
|
||||
|
||||
class JobTable: Reactor.Component {
|
||||
this var jobs = [];
|
||||
this var job_map = {};
|
||||
class JobTable extends Element {
|
||||
jobs = [];
|
||||
job_map = {};
|
||||
|
||||
function render() {
|
||||
var me = this;
|
||||
var rows = this.jobs.map(function(job, i) { return me.renderRow(job, i); });
|
||||
return <section><table .has_current .job-table>
|
||||
render() {
|
||||
let rows = this.jobs.map((job, i)=>this.renderRow(job, i));
|
||||
return (<section><table class="has_current job-table">
|
||||
<tbody key={rows.length}>
|
||||
{rows}
|
||||
</tbody>
|
||||
</table></section>;
|
||||
</table></section>);
|
||||
}
|
||||
|
||||
event click $(svg.cancel) (_, me) {
|
||||
var job = this.jobs[me.parent.parent.index];
|
||||
var id = job.id;
|
||||
handler.cancel_job(id);
|
||||
["on click at svg.cancel"](_, me) {
|
||||
let job = this.jobs[me.parentElement.parentElement.index];
|
||||
let id = job.id;
|
||||
handler.xcall("cancel_job",id);
|
||||
delete this.job_map[id];
|
||||
var i = -1;
|
||||
let i = -1;
|
||||
this.jobs.map(function(job, idx) {
|
||||
if (job.id == id) i = idx;
|
||||
});
|
||||
this.jobs.splice(i, 1);
|
||||
this.update();
|
||||
var is_remote = job.is_remote;
|
||||
this.componentUpdate();
|
||||
let is_remote = job.is_remote;
|
||||
if (job.type != "del-dir") is_remote = !is_remote;
|
||||
refreshDir(is_remote);
|
||||
}
|
||||
|
||||
function send(path, is_remote) {
|
||||
var to;
|
||||
var show_hidden;
|
||||
send(path, is_remote) {
|
||||
let to;
|
||||
let show_hidden;
|
||||
if (is_remote) {
|
||||
to = file_transfer.local_folder_view.fd.path;
|
||||
to = file_transfer.local_folder_view.fd.path; // NULL
|
||||
show_hidden = file_transfer.remote_folder_view.show_hidden;
|
||||
} else {
|
||||
to = file_transfer.remote_folder_view.fd.path;
|
||||
show_hidden = file_transfer.local_folder_view.show_hidden;
|
||||
}
|
||||
if (!to) return;
|
||||
to += handler.get_path_sep(!is_remote) + getFileName(is_remote, path);
|
||||
var id = jobIdCounter;
|
||||
to += handler.xcall("get_path_sep",!is_remote) + getFileName(is_remote, path);
|
||||
let id = jobIdCounter;
|
||||
jobIdCounter += 1;
|
||||
this.jobs.push({ type: "transfer",
|
||||
id: id, path: path, to: to,
|
||||
include_hidden: show_hidden,
|
||||
is_remote: is_remote });
|
||||
this.job_map[id] = this.jobs[this.jobs.length - 1];
|
||||
handler.send_files(id, path, to, show_hidden, is_remote);
|
||||
this.update();
|
||||
handler.xcall("send_files",id, path, to, show_hidden, is_remote);
|
||||
this.componentUpdate();
|
||||
}
|
||||
|
||||
function addDelDir(path, is_remote) {
|
||||
var id = jobIdCounter;
|
||||
addDelDir(path, is_remote) {
|
||||
let id = jobIdCounter;
|
||||
jobIdCounter += 1;
|
||||
this.jobs.push({ type: "del-dir", id: id, path: path, is_remote: is_remote });
|
||||
this.job_map[id] = this.jobs[this.jobs.length - 1];
|
||||
handler.remove_dir_all(id, path, is_remote);
|
||||
this.update();
|
||||
handler.xcall("remove_dir_all",id, path, is_remote);
|
||||
this.componentUpdate();
|
||||
}
|
||||
|
||||
function getSvg(job) {
|
||||
getSvg(job) {
|
||||
if (job.type == "transfer") {
|
||||
return svg_send;
|
||||
} else if (job.type == "del-dir") {
|
||||
@ -140,19 +143,19 @@ class JobTable: Reactor.Component {
|
||||
}
|
||||
}
|
||||
|
||||
function getStatus(job) {
|
||||
getStatus(job) {
|
||||
if (!job.entries) return translate("Waiting");
|
||||
var i = job.file_num + 1;
|
||||
var n = job.num_entries || job.entries.length;
|
||||
let i = job.file_num + 1;
|
||||
let n = job.num_entries || job.entries.length;
|
||||
if (i > n) i = n;
|
||||
var res = i + ' / ' + n + " " + translate("files");
|
||||
let res = i + ' / ' + n + " " + translate("files");
|
||||
if (job.total_size > 0) {
|
||||
var s = getSize(0, job.finished_size);
|
||||
let s = getSize(0, job.finished_size);
|
||||
if (s) s += " / ";
|
||||
res += ", " + s + getSize(0, job.total_size);
|
||||
}
|
||||
// below has problem if some file skipped
|
||||
var percent = job.total_size == 0 ? 100 : (100. * job.finished_size / job.total_size).toInteger(); // (100. * i / (n || 1)).toInteger();
|
||||
let percent = job.total_size == 0 ? 100 : (100. * job.finished_size / job.total_size).toInteger(); // (100. * i / (n || 1)).toInteger();
|
||||
if (job.finished) percent = '100';
|
||||
if (percent) res += ", " + percent + "%";
|
||||
if (job.finished) res = translate("Finished") + " " + res;
|
||||
@ -160,17 +163,18 @@ class JobTable: Reactor.Component {
|
||||
return res;
|
||||
}
|
||||
|
||||
function updateJob(job) {
|
||||
var el = this.select("div[id=s" + job.id + "]");
|
||||
updateJob(job) {
|
||||
let el = this.$("div#s" + job.id); // TODO TEST
|
||||
console.log("updateJob el",el);
|
||||
if (el) el.text = this.getStatus(job);
|
||||
}
|
||||
|
||||
function updateJobStatus(id, file_num = -1, err = null, speed = null, finished_size = 0) {
|
||||
var job = this.job_map[id];
|
||||
updateJobStatus(id, file_num = -1, err = null, speed = null, finished_size = 0) {
|
||||
let job = this.job_map[id];
|
||||
if (!job) return;
|
||||
if (file_num < job.file_num) return;
|
||||
job.file_num = file_num;
|
||||
var n = job.num_entries || job.entries.length;
|
||||
let n = job.num_entries || job.entries.length;
|
||||
job.finished = job.file_num >= n - 1 || err == "cancel";
|
||||
job.finished_size = finished_size;
|
||||
job.speed = speed || 0;
|
||||
@ -178,151 +182,158 @@ class JobTable: Reactor.Component {
|
||||
if (job.type == "del-dir") {
|
||||
if (job.finished) {
|
||||
if (!err) {
|
||||
handler.remove_dir(job.id, job.path, job.is_remote);
|
||||
handler.xcall("remove_dir",job.id, job.path, job.is_remote);
|
||||
refreshDir(job.is_remote);
|
||||
}
|
||||
} else if (!job.no_confirm) {
|
||||
handler.confirm_delete_files(id, job.file_num + 1);
|
||||
handler.xcall("confirm_delete_files",id, job.file_num + 1);
|
||||
}
|
||||
} else if (job.finished || file_num == -1) {
|
||||
refreshDir(!job.is_remote);
|
||||
}
|
||||
}
|
||||
|
||||
function renderRow(job, i) {
|
||||
var svg = this.getSvg(job);
|
||||
return <tr class={job.is_remote ? "is_remote" : ""}><td>
|
||||
renderRow(job, i) {
|
||||
svg = this.getSvg(job);
|
||||
return (<tr class={job.is_remote ? "is_remote" : ""}><td>
|
||||
{svg}
|
||||
<div .text>
|
||||
<div .path>{job.path}</div>
|
||||
<div class="text">
|
||||
<div class="path">{job.path}</div>
|
||||
<div id={"s" + job.id}>{this.getStatus(job)}</div>
|
||||
</div>
|
||||
{svg_cancel}
|
||||
</td></tr>;
|
||||
</td></tr>);
|
||||
}
|
||||
}
|
||||
|
||||
class FolderView : Reactor.Component {
|
||||
this var fd = {};
|
||||
this var history = [];
|
||||
this var show_hidden = false;
|
||||
class FolderView extends Element {
|
||||
fd = {};
|
||||
history = [];
|
||||
show_hidden = false;
|
||||
select_dir;
|
||||
|
||||
function sep() {
|
||||
return handler.get_path_sep(this.is_remote);
|
||||
sep() {
|
||||
return handler.xcall("get_path_sep",this.is_remote);
|
||||
}
|
||||
|
||||
function this(params) {
|
||||
this(params) {
|
||||
this.is_remote = params.is_remote;
|
||||
if (this.is_remote) {
|
||||
this.show_hidden = !!handler.get_option("remote_show_hidden");
|
||||
this.show_hidden = !!handler.xcall("get_option","remote_show_hidden");
|
||||
} else {
|
||||
this.show_hidden = !!handler.get_option("local_show_hidden");
|
||||
this.show_hidden = !!handler.xcall("get_option","local_show_hidden");
|
||||
}
|
||||
if (!this.is_remote) {
|
||||
var dir = handler.get_option("local_dir");
|
||||
let dir = handler.xcall("get_option","local_dir");
|
||||
if (dir) {
|
||||
this.fd = handler.read_dir(dir, this.show_hidden);
|
||||
this.fd = handler.xcall("read_dir",dir, this.show_hidden);
|
||||
if (this.fd) return;
|
||||
}
|
||||
this.fd = handler.read_dir(handler.get_home_dir(), this.show_hidden);
|
||||
this.fd = handler.xcall("read_dir",handler.xcall("get_home_dir"), this.show_hidden);
|
||||
}
|
||||
}
|
||||
|
||||
// sort predicate
|
||||
function foldersFirst(a, b) {
|
||||
foldersFirst(a, b) {
|
||||
if (a.type <= 3 && b.type > 3) return -1;
|
||||
if (a.type > 3 && b.type <= 3) return +1;
|
||||
if (a.name == b.name) return 0;
|
||||
return a.name.toLowerCase().lexicalCompare(b.name.toLowerCase());
|
||||
return a.name.toLowerCase().lexicalCompare(b.name.toLowerCase()); // TODO lexicalCompare
|
||||
}
|
||||
|
||||
function render()
|
||||
render()
|
||||
{
|
||||
return <section>
|
||||
return (<section>
|
||||
{this.renderTitle()}
|
||||
{this.renderNavBar()}
|
||||
{this.renderOpBar()}
|
||||
{this.renderTable()}
|
||||
</section>;
|
||||
</section>);
|
||||
}
|
||||
|
||||
function renderTitle() {
|
||||
return <div .title>
|
||||
renderTitle() {
|
||||
return (<div class="title">
|
||||
{svg_computer}
|
||||
<div .platform>{platformSvg(handler.get_platform(this.is_remote), "white")}</div>
|
||||
<div class="platform">{platformSvg(handler.xcall("get_platform",this.is_remote), "white")}</div>
|
||||
<div><span>{translate(this.is_remote ? "Remote Computer" : "Local Computer")}</span></div>
|
||||
</div>
|
||||
</div>)
|
||||
}
|
||||
|
||||
function renderNavBar() {
|
||||
return <div .toolbar .navbar>
|
||||
<div .home .button>{svg_home}</div>
|
||||
<div .goback .button>{svg_arrow}</div>
|
||||
<div .goup .button>{svg_arrow}</div>
|
||||
renderNavBar() {
|
||||
return <div class="toolbar navbar">
|
||||
<div class="home button">{svg_home}</div>
|
||||
<div class="goback button">{svg_arrow}</div>
|
||||
<div class="goup button">{svg_arrow}</div>
|
||||
{this.renderSelect()}
|
||||
<div .refresh .button>{svg_refresh}</div>
|
||||
<div class="refresh button">{svg_refresh}</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
function renderSelect() {
|
||||
return <select editable .select-dir @{this.select_dir}>
|
||||
// TODO
|
||||
componentDidMount(){
|
||||
this.select_dir = this.$("select.select-dir")
|
||||
}
|
||||
|
||||
renderSelect() {
|
||||
return (<select editable class="select-dir">
|
||||
<option>/</option>
|
||||
</select>;
|
||||
</select>);
|
||||
}
|
||||
|
||||
function renderOpBar() {
|
||||
renderOpBar() {
|
||||
if (this.is_remote) {
|
||||
return <div .toolbar .remote>
|
||||
<div .send .button>{svg_send}<span>{translate('Receive')}</span></div>
|
||||
<div .spacer></div>
|
||||
<div .add-folder .button>{svg_add_folder}</div>
|
||||
<div .trash .button>{svg_trash}</div>
|
||||
</div>;
|
||||
return (<div class="toolbar remote">
|
||||
<div class="send button">{svg_send}<span>{translate('Receive')}</span></div>
|
||||
<div class="spacer"></div>
|
||||
<div class="add-folder button">{svg_add_folder}</div>
|
||||
<div class="trash button">{svg_trash}</div>
|
||||
</div>);
|
||||
}
|
||||
return <div .toolbar>
|
||||
<div .add-folder .button>{svg_add_folder}</div>
|
||||
<div .trash .button>{svg_trash}</div>
|
||||
<div .spacer></div>
|
||||
<div .send .button><span>{translate('Send')}</span>{svg_send}</div>
|
||||
</div>;
|
||||
return (<div class="toolbar">
|
||||
<div class="add-folder button">{svg_add_folder}</div>
|
||||
<div class="trash button">{svg_trash}</div>
|
||||
<div class="spacer"></div>
|
||||
<div class="send button"><span>{translate('Send')}</span>{svg_send}</div>
|
||||
</div>);
|
||||
}
|
||||
|
||||
function get_updated() {
|
||||
this.table.sortRows(false);
|
||||
get_updated() {
|
||||
this.table.sortRows(false); // TODO sortRows
|
||||
if (this.fd && this.fd.path) this.select_dir.value = this.fd.path;
|
||||
}
|
||||
|
||||
function renderTable() {
|
||||
var fd = this.fd;
|
||||
var entries = fd.entries || [];
|
||||
var table = this.table;
|
||||
renderTable() {
|
||||
let fd = this.fd;
|
||||
let entries = fd.entries || [];
|
||||
let table = this.table;
|
||||
if (!table || !table.sortBy) {
|
||||
entries.sort(this.foldersFirst);
|
||||
entries.sort(this.foldersFirst); // TODO sort function
|
||||
}
|
||||
var me = this;
|
||||
var path = fd.path;
|
||||
let path = fd.path;
|
||||
if (path != "/" && path) {
|
||||
entries = [{ name: "..", type: 1 }].concat(entries);
|
||||
}
|
||||
var rows = entries.map(function(e) { return me.renderRow(e); });
|
||||
var id = (this.is_remote ? "remote" : "local") + "-folder-view";
|
||||
return <table @{this.table} .folder-view .has_current id={id}>
|
||||
let rows = entries.map(e=>this.renderRow(e));
|
||||
let id = (this.is_remote ? "remote" : "local") + "-folder-view";
|
||||
//@{} return (<table @{this.table} .folder-view .has_current id={id}>
|
||||
|
||||
return (<table class="folder-view has_current" id={id}>
|
||||
<thead>
|
||||
<tr><th></th><th .sortable>{translate('Name')}</th><th .sortable>{translate('Modified')}</th><th .sortable>{translate('Size')}</th></tr>
|
||||
<tr><th></th><th class="sortable">{translate('Name')}</th><th class="sortable">{translate('Modified')}</th><th class="sortable">{translate('Size')}</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows}
|
||||
</tbody>
|
||||
<popup>
|
||||
<menu.context id={id}>
|
||||
<li #switch-hidden class={this.show_hidden ? "selected" : ""}><span>{svg_checkmark}</span>{translate('Show Hidden Files')}</li>
|
||||
<menu class="context" id={id}>
|
||||
<li id="switch-hidden" class={this.show_hidden ? "selected" : ""}><span>{svg_checkmark}</span>{translate('Show Hidden Files')}</li>
|
||||
</menu>
|
||||
</popup>
|
||||
</table>;
|
||||
</table>);
|
||||
}
|
||||
|
||||
function joinPath(name) {
|
||||
var path = this.fd.path;
|
||||
joinPath(name) {
|
||||
let path = this.fd.path;
|
||||
if (path == "/") {
|
||||
if (this.sep() == "/") return this.sep() + name;
|
||||
else return name;
|
||||
@ -330,91 +341,89 @@ class FolderView : Reactor.Component {
|
||||
return path + (path[path.length - 1] == this.sep() ? "" : this.sep()) + name;
|
||||
}
|
||||
|
||||
function attached() {
|
||||
var me = this;
|
||||
this.table.onRowDoubleClick = function (row) {
|
||||
var type = row[0].attributes["type"];
|
||||
attached() {
|
||||
this.table.onRowDoubleClick = (row)=>{
|
||||
let type = row[0].attributes["type"];
|
||||
if (type > 3) return;
|
||||
var name = row[1].text;
|
||||
var path = name == ".." ? getParentPath(me.is_remote, me.fd.path) : me.joinPath(name);
|
||||
me.goto(path, true);
|
||||
let name = row[1].text;
|
||||
let path = name == ".." ? getParentPath(this.is_remote, this.fd.path) : this.joinPath(name);
|
||||
this.goto(path, true);
|
||||
}
|
||||
this.get_updated();
|
||||
}
|
||||
|
||||
function goto(path, push) {
|
||||
goto(path, push) {
|
||||
if (!path) return;
|
||||
if (this.sep() == "\\" && path.length == 2) { // windows drive
|
||||
path += "\\";
|
||||
}
|
||||
if (push) this.pushHistory();
|
||||
if (this.is_remote) {
|
||||
handler.read_remote_dir(path, this.show_hidden);
|
||||
handler.xcall("read_remote_dir",path, this.show_hidden);
|
||||
} else {
|
||||
var fd = handler.read_dir(path, this.show_hidden);
|
||||
var fd = handler.xcall("read_dir",path, this.show_hidden);
|
||||
this.refresh({ fd: fd });
|
||||
}
|
||||
}
|
||||
|
||||
function refresh(data) {
|
||||
refresh(data) {
|
||||
if (!data.fd || !data.fd.path) return;
|
||||
if (this.is_remote && !remote_home_dir) {
|
||||
remote_home_dir = data.fd.path;
|
||||
}
|
||||
this.update(data);
|
||||
var me = this;
|
||||
self.timer(1ms, function() { me.get_updated(); });
|
||||
this.componentUpdate(data);
|
||||
setTimeout(()=>this.get_updated(),1);
|
||||
}
|
||||
|
||||
function renderRow(entry) {
|
||||
var path;
|
||||
renderRow(entry) {
|
||||
let path;
|
||||
if (this.is_remote) {
|
||||
path = handler.get_icon_path(entry.type, getExt(entry.name));
|
||||
path = handler.xcall("get_icon_path",entry.type, getExt(entry.name));
|
||||
} else {
|
||||
path = this.joinPath(entry.name);
|
||||
}
|
||||
var tm = entry.time ? new Date(entry.time.toFloat() * 1000.).toLocaleString() : 0;
|
||||
return <tr role="option">
|
||||
let tm = entry.time ? new Date(entry.time.toFloat() * 1000.).toLocaleString() : 0; // TODO toFloat()
|
||||
return (<tr role="option">
|
||||
<td type={entry.type} filename={path}></td>
|
||||
<td>{entry.name}</td>
|
||||
<td value={entry.time || 0}>{tm || ""}</td>
|
||||
<td value={entry.size || 0}>{getSize(entry.type, entry.size)}</td>
|
||||
</tr>;
|
||||
</tr>);
|
||||
}
|
||||
|
||||
event click $(#switch-hidden) {
|
||||
["on click at #switch-hidden"]() {
|
||||
this.show_hidden = !this.show_hidden;
|
||||
this.refreshDir();
|
||||
}
|
||||
|
||||
event click $(.goup) () {
|
||||
var path = this.fd.path;
|
||||
["on click at .goup"]() {
|
||||
let path = this.fd.path;
|
||||
if (!path || path == "/") return;
|
||||
path = getParentPath(this.is_remote, path);
|
||||
this.goto(path, true);
|
||||
}
|
||||
|
||||
event click $(.goback) () {
|
||||
var path = this.history.pop();
|
||||
["on click at .goback"] () {
|
||||
let path = this.history.pop();
|
||||
if (!path) return;
|
||||
this.goto(path, false);
|
||||
}
|
||||
|
||||
event click $(.trash) () {
|
||||
var rows = this.getCurrentRows();
|
||||
["on click at .trash"]() {
|
||||
let rows = this.getCurrentRows();
|
||||
if (!rows || rows.length == 0) return;
|
||||
|
||||
var delete_dirs = new Array();
|
||||
let delete_dirs = new Array();
|
||||
|
||||
for (var i = 0; i < rows.length; ++i) {
|
||||
var row = rows[i];
|
||||
for (let i = 0; i < rows.length; ++i) {
|
||||
let row = rows[i];
|
||||
|
||||
var path = row[0];
|
||||
var type = row[1];
|
||||
let path = row[0];
|
||||
let type = row[1];
|
||||
|
||||
var new_history = [];
|
||||
for (var j = 0; j < this.history.length; ++j) {
|
||||
var h = this.history[j];
|
||||
let new_history = [];
|
||||
for (let j = 0; j < this.history.length; ++j) {
|
||||
let h = this.history[j];
|
||||
if ((h + this.sep()).indexOf(path + this.sep()) == -1) new_history.push(h);
|
||||
}
|
||||
this.history = new_history;
|
||||
@ -424,97 +433,96 @@ class FolderView : Reactor.Component {
|
||||
confirmDelete(path, this.is_remote);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < delete_dirs.length; ++i) {
|
||||
for (let i = 0; i < delete_dirs.length; ++i) {
|
||||
file_transfer.job_table.addDelDir(delete_dirs[i], this.is_remote);
|
||||
}
|
||||
}
|
||||
|
||||
event click $(.add-folder) () {
|
||||
var me = this;
|
||||
["on click at .add-folder"]() {
|
||||
let me = this;
|
||||
msgbox("custom", translate("Create Folder"), "<div .form> \
|
||||
<div>" + translate("Please enter the folder name") + ":</div> \
|
||||
<div><input|text(name) .outline-focus /></div> \
|
||||
</div>", function(res=null) {
|
||||
if (!res) return;
|
||||
if (!res.name) return;
|
||||
var name = res.name.trim();
|
||||
let name = res.name.trim();
|
||||
if (!name) return;
|
||||
if (name.indexOf(me.sep()) >= 0) {
|
||||
handler.msgbox("custom-error", "Create Folder", "Invalid folder name");
|
||||
return;
|
||||
}
|
||||
var path = me.joinPath(name);
|
||||
handler.create_dir(jobIdCounter, path, me.is_remote);
|
||||
let path = me.joinPath(name);
|
||||
handler.xcall("create_dir",jobIdCounter, path, me.is_remote);
|
||||
create_dir_jobs[jobIdCounter] = { is_remote: me.is_remote, path: path };
|
||||
jobIdCounter += 1;
|
||||
});
|
||||
}
|
||||
|
||||
function refreshDir() {
|
||||
refreshDir() {
|
||||
this.goto(this.fd.path, false);
|
||||
}
|
||||
|
||||
event click $(.refresh) () {
|
||||
["on click at .refresh"]() {
|
||||
this.refreshDir();
|
||||
}
|
||||
|
||||
event click $(.home) () {
|
||||
var path = this.is_remote ? remote_home_dir : handler.get_home_dir();
|
||||
["on click at .home"]() {
|
||||
let path = this.is_remote ? remote_home_dir : handler.xcall("get_home_dir");
|
||||
if (!path) return;
|
||||
if (path == this.fd.path) return;
|
||||
this.goto(path, true);
|
||||
}
|
||||
|
||||
function getCurrentRow() {
|
||||
var row = this.table.getCurrentRow();
|
||||
getCurrentRow() {
|
||||
let row = this.table.getCurrentRow(); // TEST getCurrentRow
|
||||
if (!row) return;
|
||||
var name = row[1].text;
|
||||
let name = row[1].text;
|
||||
if (!name || name == "..") return;
|
||||
var type = row[0].attributes["type"];
|
||||
let type = row[0].attributes["type"];
|
||||
return [this.joinPath(name), type];
|
||||
}
|
||||
|
||||
function getCurrentRows() {
|
||||
var rows = this.table.getCurrentRows();
|
||||
getCurrentRows() {
|
||||
let rows = this.table.getCurrentRows();
|
||||
if (!rows || rows.length== 0) return;
|
||||
|
||||
var records = new Array();
|
||||
let records = new Array();
|
||||
|
||||
for (var i = 0; i < rows.length; ++i) {
|
||||
var name = rows[i][1].text;
|
||||
for (let i = 0; i < rows.length; ++i) {
|
||||
let name = rows[i][1].text;
|
||||
if (!name || name == "..") continue;
|
||||
|
||||
var type = rows[i][0].attributes["type"];
|
||||
let type = rows[i][0].attributes["type"];
|
||||
records.push([this.joinPath(name), type]);
|
||||
}
|
||||
return records;
|
||||
}
|
||||
|
||||
event click $(.send) () {
|
||||
var rows = this.getCurrentRows();
|
||||
["on click at .send"]() {
|
||||
let rows = this.getCurrentRows();
|
||||
if (!rows || rows.length == 0) return;
|
||||
for (var i = 0; i < rows.length; ++i) {
|
||||
for (let i = 0; i < rows.length; ++i) {
|
||||
file_transfer.job_table.send(rows[i][0], this.is_remote);
|
||||
}
|
||||
}
|
||||
|
||||
event change $(.select-dir) (_, el) {
|
||||
var x = getTime() - last_key_time;
|
||||
["on change at .select-dir"](_, el) {
|
||||
var x = getTime() - last_key_time; // TODO getTime
|
||||
if (x < 1000) return;
|
||||
if (this.fd.path != el.value) {
|
||||
this.goto(el.value, true);
|
||||
}
|
||||
}
|
||||
|
||||
event keydown $(.select-dir) (evt, me) {
|
||||
if (evt.keyCode == Event.VK_ENTER ||
|
||||
(view.mediaVar("platform") == "OSX" && evt.keyCode == 0x4C)) {
|
||||
["on keydown at .select-dir"](evt, me) {
|
||||
if (evt.code == "KeyRETURN") { // TODO TEST mac
|
||||
this.goto(me.value, true);
|
||||
}
|
||||
}
|
||||
|
||||
function pushHistory() {
|
||||
var path = this.fd.path;
|
||||
pushHistory() {
|
||||
let path = this.fd.path;
|
||||
if (!path) return;
|
||||
if (path != this.history[this.history.length - 1]) this.history.push(path);
|
||||
}
|
||||
@ -522,32 +530,37 @@ class FolderView : Reactor.Component {
|
||||
|
||||
var file_transfer;
|
||||
|
||||
class FileTransfer: Reactor.Component {
|
||||
function this() {
|
||||
file_transfer = this;
|
||||
class FileTransfer extends Element {
|
||||
this() {
|
||||
file_transfer = this;
|
||||
}
|
||||
// TODO @{}
|
||||
// <FolderView is_remote={false} @{this.local_folder_view} />
|
||||
// <FolderView is_remote={true} @{this.remote_folder_view}/>
|
||||
// <JobTable @{this.job_table} />
|
||||
|
||||
function render() {
|
||||
return <div #file-transfer>
|
||||
<FolderView is_remote={false} @{this.local_folder_view} />
|
||||
<FolderView is_remote={true} @{this.remote_folder_view}/>
|
||||
<JobTable @{this.job_table} />
|
||||
</div>;
|
||||
render() {
|
||||
return (<div id="file-transfer">
|
||||
<FolderView is_remote={false} />
|
||||
<FolderView is_remote={true} />
|
||||
<JobTable />
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
||||
function initializeFileTransfer()
|
||||
export function initializeFileTransfer()
|
||||
{
|
||||
$(#file-transfer-wrapper).content(<FileTransfer />);
|
||||
$(#video-wrapper).style.set { visibility: "hidden", position: "absolute" };
|
||||
$(#file-transfer-wrapper).style.set { display: "block" };
|
||||
$("#file-transfer-wrapper").content(<FileTransfer />);
|
||||
$("#video-wrapper").style.setProperty("visibility","hidden");
|
||||
$("#video-wrapper").style.setProperty("position","absolute");
|
||||
$("#file-transfer-wrapper").style.setProperty("display","block");
|
||||
}
|
||||
|
||||
handler.updateFolderFiles = function(fd) {
|
||||
fd.entries = fd.entries || [];
|
||||
if (fd.id > 0) {
|
||||
var jt = file_transfer.job_table;
|
||||
var job = jt.job_map[fd.id];
|
||||
let jt = file_transfer.job_table;
|
||||
let job = jt.job_map[fd.id];
|
||||
if (job) {
|
||||
job.file_num = -1;
|
||||
job.total_size = fd.total_size;
|
||||
@ -565,7 +578,7 @@ handler.jobProgress = function(id, file_num, speed, finished_size) {
|
||||
}
|
||||
|
||||
handler.jobDone = function(id, file_num = -1) {
|
||||
var job = deleting_single_file_jobs[id] || create_dir_jobs[id];
|
||||
let job = deleting_single_file_jobs[id] || create_dir_jobs[id];
|
||||
if (job) {
|
||||
refreshDir(job.is_remote);
|
||||
return;
|
||||
@ -604,7 +617,7 @@ function confirmDelete(path, is_remote) {
|
||||
<div.ellipsis style=\"font-weight: bold;\">" + path + "</div> \
|
||||
</div>", function(res=null) {
|
||||
if (res) {
|
||||
handler.remove_file(jobIdCounter, path, 0, is_remote);
|
||||
handler.xcall("remove_file",jobIdCounter, path, 0, is_remote);
|
||||
deleting_single_file_jobs[jobIdCounter] = { is_remote: is_remote, path: path };
|
||||
jobIdCounter += 1;
|
||||
}
|
||||
@ -618,7 +631,7 @@ handler.confirmDeleteFiles = function(id, i, name) {
|
||||
var n = job.num_entries;
|
||||
if (i >= n) return;
|
||||
var file_path = job.path;
|
||||
if (name) file_path += handler.get_path_sep(job.is_remote) + name;
|
||||
if (name) file_path += handler.xcall("get_path_sep",job.is_remote) + name;
|
||||
msgbox("custom-skip", "Confirm Delete", "<div .form> \
|
||||
<div>" + translate('Deleting') + " #" + (i + 1) + " / " + n + " " + translate('files') + ".</div> \
|
||||
<div>" + translate('Are you sure you want to delete this file?') + "</div> \
|
||||
@ -633,18 +646,18 @@ handler.confirmDeleteFiles = function(id, i, name) {
|
||||
} else {
|
||||
job.no_confirm = res.remember;
|
||||
if (job.no_confirm) handler.set_no_confirm(id);
|
||||
handler.remove_file(id, file_path, i, job.is_remote);
|
||||
handler.xcall("remove_file",id, file_path, i, job.is_remote);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function save_file_transfer_close_state() {
|
||||
export function save_file_transfer_close_state() {
|
||||
var local_dir = file_transfer.local_folder_view.fd.path || "";
|
||||
var local_show_hidden = file_transfer.local_folder_view.show_hidden ? "Y" : "";
|
||||
var remote_dir = file_transfer.remote_folder_view.fd.path || "";
|
||||
var remote_show_hidden = file_transfer.remote_folder_view.show_hidden ? "Y" : "";
|
||||
handler.save_close_state("local_dir", local_dir);
|
||||
handler.save_close_state("local_show_hidden", local_show_hidden);
|
||||
handler.save_close_state("remote_dir", remote_dir);
|
||||
handler.save_close_state("remote_show_hidden", remote_show_hidden);
|
||||
handler.xcall("save_close_state","local_dir", local_dir);
|
||||
handler.xcall("save_close_state","local_show_hidden", local_show_hidden);
|
||||
handler.xcall("save_close_state","remote_dir", remote_dir);
|
||||
handler.xcall("save_close_state","remote_show_hidden", remote_show_hidden);
|
||||
}
|
||||
|
386
src/ui/header.js
386
src/ui/header.js
@ -1,74 +1,76 @@
|
||||
var pi = handler.get_default_pi(); // peer information
|
||||
import { handler,view,is_file_transfer,setWindowButontsAndIcon,translate,msgbox,adjustBorder,is_osx,is_xfce,svg_chat,svg_checkmark, is_linux } from "./common.js";
|
||||
import {$,$$} from "@sciter";
|
||||
import { adaptDisplay,is_port_forward } from "./remote.js";
|
||||
var pi = handler.xcall("get_default_pi"); // peer information
|
||||
|
||||
var chat_msgs = [];
|
||||
|
||||
var svg_fullscreen = <svg viewBox="0 0 357 357">
|
||||
const svg_fullscreen = (<svg viewBox="0 0 357 357">
|
||||
<path d="M51,229.5H0V357h127.5v-51H51V229.5z M0,127.5h51V51h76.5V0H0V127.5z M306,306h-76.5v51H357V229.5h-51V306z M229.5,0v51 H306v76.5h51V0H229.5z"/>
|
||||
</svg>;
|
||||
var svg_action = <svg viewBox="-91 0 512 512"><path d="M315 211H191L298 22a15 15 0 00-13-22H105c-6 0-12 4-14 10L1 281a15 15 0 0014 20h127L61 491a15 15 0 0025 16l240-271a15 15 0 00-11-25z"/></svg>;
|
||||
var svg_display = <svg viewBox="0 0 640 512">
|
||||
</svg>);
|
||||
const svg_action = (<svg viewBox="-91 0 512 512"><path d="M315 211H191L298 22a15 15 0 00-13-22H105c-6 0-12 4-14 10L1 281a15 15 0 0014 20h127L61 491a15 15 0 0025 16l240-271a15 15 0 00-11-25z"/></svg>);
|
||||
const svg_display = (<svg viewBox="0 0 640 512">
|
||||
<path d="M592 0H48A48 48 0 0 0 0 48v320a48 48 0 0 0 48 48h240v32H112a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16H352v-32h240a48 48 0 0 0 48-48V48a48 48 0 0 0-48-48zm-16 352H64V64h512z"/>
|
||||
</svg>;
|
||||
var svg_secure = <svg viewBox="0 0 347.97 347.97">
|
||||
</svg>);
|
||||
const svg_secure = (<svg viewBox="0 0 347.97 347.97">
|
||||
<path fill="#3F7D46" d="m317.31 54.367c-59.376 0-104.86-16.964-143.33-54.367-38.461 37.403-83.947 54.367-143.32 54.367 0 97.405-20.155 236.94 143.32 293.6 163.48-56.666 143.33-196.2 143.33-293.6zm-155.2 171.41-47.749-47.756 21.379-21.378 26.37 26.376 50.121-50.122 21.378 21.378-71.499 71.502z"/>
|
||||
</svg>;
|
||||
var svg_insecure = <svg viewBox="0 0 347.97 347.97"><path d="M317.469 61.615c-59.442 0-104.976-16.082-143.489-51.539-38.504 35.457-84.04 51.539-143.479 51.539 0 92.337-20.177 224.612 143.479 278.324 163.661-53.717 143.489-185.992 143.489-278.324z" fill="none" stroke="red" stroke-width="14.827"/><g fill="red"><path d="M238.802 115.023l-111.573 114.68-8.6-8.367L230.2 106.656z"/><path d="M125.559 108.093l114.68 111.572-8.368 8.601-114.68-111.572z"/></g></svg>;
|
||||
var svg_insecure_relay = <svg viewBox="0 0 347.97 347.97"><path d="M317.469 61.615c-59.442 0-104.976-16.082-143.489-51.539-38.504 35.457-84.04 51.539-143.479 51.539 0 92.337-20.177 224.612 143.479 278.324 163.661-53.717 143.489-185.992 143.489-278.324z" fill="none" stroke="red" stroke-width="14.827"/><g fill="red"><path d="M231.442 247.498l-7.754-10.205c-17.268 12.441-38.391 17.705-59.478 14.822-21.087-2.883-39.613-13.569-52.166-30.088-25.916-34.101-17.997-82.738 17.65-108.42 32.871-23.685 78.02-19.704 105.172 7.802l-32.052 7.987 3.082 12.369 48.722-12.142-11.712-46.998-12.822 3.196 4.496 18.039c-31.933-24.008-78.103-25.342-112.642-.458-31.361 22.596-44.3 60.436-35.754 94.723 2.77 11.115 7.801 21.862 15.192 31.588 30.19 39.727 88.538 47.705 130.066 17.785z"/></g></svg>;
|
||||
var svg_secure_relay = <svg viewBox="0 0 347.97 347.97"><path d="M317.469 61.615c-59.442 0-104.976-16.082-143.489-51.539-38.504 35.457-84.04 51.539-143.479 51.539 0 92.337-20.177 224.612 143.479 278.324 163.661-53.717 143.489-185.992 143.489-278.324z" fill="#3f7d46" stroke="#3f7d46" stroke-width="14.827"/><g fill="red"><path d="M231.442 247.498l-7.754-10.205c-17.268 12.441-38.391 17.705-59.478 14.822-21.087-2.883-39.613-13.569-52.166-30.088-25.916-34.101-17.997-82.738 17.65-108.42 32.871-23.685 78.02-19.704 105.172 7.802l-32.052 7.987 3.082 12.369 48.722-12.142-11.712-46.998-12.822 3.196 4.496 18.039c-31.933-24.008-78.103-25.342-112.642-.458-31.361 22.596-44.3 60.436-35.754 94.723 2.77 11.115 7.801 21.862 15.192 31.588 30.19 39.727 88.538 47.705 130.066 17.785z" fill="#fff"/></g></svg>;
|
||||
</svg>);
|
||||
const svg_insecure = (<svg viewBox="0 0 347.97 347.97"><path d="M317.469 61.615c-59.442 0-104.976-16.082-143.489-51.539-38.504 35.457-84.04 51.539-143.479 51.539 0 92.337-20.177 224.612 143.479 278.324 163.661-53.717 143.489-185.992 143.489-278.324z" fill="none" stroke="red" stroke-width="14.827"/><g fill="red"><path d="M238.802 115.023l-111.573 114.68-8.6-8.367L230.2 106.656z"/><path d="M125.559 108.093l114.68 111.572-8.368 8.601-114.68-111.572z"/></g></svg>);
|
||||
const svg_insecure_relay = (<svg viewBox="0 0 347.97 347.97"><path d="M317.469 61.615c-59.442 0-104.976-16.082-143.489-51.539-38.504 35.457-84.04 51.539-143.479 51.539 0 92.337-20.177 224.612 143.479 278.324 163.661-53.717 143.489-185.992 143.489-278.324z" fill="none" stroke="red" stroke-width="14.827"/><g fill="red"><path d="M231.442 247.498l-7.754-10.205c-17.268 12.441-38.391 17.705-59.478 14.822-21.087-2.883-39.613-13.569-52.166-30.088-25.916-34.101-17.997-82.738 17.65-108.42 32.871-23.685 78.02-19.704 105.172 7.802l-32.052 7.987 3.082 12.369 48.722-12.142-11.712-46.998-12.822 3.196 4.496 18.039c-31.933-24.008-78.103-25.342-112.642-.458-31.361 22.596-44.3 60.436-35.754 94.723 2.77 11.115 7.801 21.862 15.192 31.588 30.19 39.727 88.538 47.705 130.066 17.785z"/></g></svg>);
|
||||
const svg_secure_relay = (<svg viewBox="0 0 347.97 347.97"><path d="M317.469 61.615c-59.442 0-104.976-16.082-143.489-51.539-38.504 35.457-84.04 51.539-143.479 51.539 0 92.337-20.177 224.612 143.479 278.324 163.661-53.717 143.489-185.992 143.489-278.324z" fill="#3f7d46" stroke="#3f7d46" stroke-width="14.827"/><g fill="red"><path d="M231.442 247.498l-7.754-10.205c-17.268 12.441-38.391 17.705-59.478 14.822-21.087-2.883-39.613-13.569-52.166-30.088-25.916-34.101-17.997-82.738 17.65-108.42 32.871-23.685 78.02-19.704 105.172 7.802l-32.052 7.987 3.082 12.369 48.722-12.142-11.712-46.998-12.822 3.196 4.496 18.039c-31.933-24.008-78.103-25.342-112.642-.458-31.361 22.596-44.3 60.436-35.754 94.723 2.77 11.115 7.801 21.862 15.192 31.588 30.19 39.727 88.538 47.705 130.066 17.785z" fill="#fff"/></g></svg>);
|
||||
|
||||
var cur_window_state = view.state;
|
||||
|
||||
var cur_window_state = view.windowState;
|
||||
function check_state_change() {
|
||||
if (view.windowState != cur_window_state) {
|
||||
stateChanged();
|
||||
}
|
||||
self.timer(30ms, check_state_change);
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
check_state_change();
|
||||
// check_state_change;
|
||||
setInterval(() => {
|
||||
if (view.state != cur_window_state) {
|
||||
stateChanged();
|
||||
}
|
||||
}, 30);
|
||||
} else {
|
||||
view << event statechange {
|
||||
view.on("statechange",()=>{
|
||||
stateChanged();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function get_id() {
|
||||
return handler.get_option('alias') || handler.get_id()
|
||||
return handler.xcall("get_option","alias") || handler.xcall("get_id")
|
||||
}
|
||||
|
||||
function stateChanged() {
|
||||
stdout.println('state changed from ' + cur_window_state + ' -> ' + view.windowState);
|
||||
cur_window_state = view.windowState;
|
||||
console.log('state changed from ' + cur_window_state + ' -> ' + view.state);
|
||||
cur_window_state = view.state;
|
||||
adjustBorder();
|
||||
adaptDisplay();
|
||||
if (cur_window_state != View.WINDOW_MINIMIZED) {
|
||||
if (cur_window_state != Window.WINDOW_MINIMIZED) {
|
||||
view.focus = handler; // to make focus away from restore/maximize button, so that enter key work
|
||||
}
|
||||
var fs = view.windowState == View.WINDOW_FULL_SCREEN;
|
||||
var el = $(#fullscreen);
|
||||
if (el) el.attributes.toggleClass("active", fs);
|
||||
el = $(#maximize);
|
||||
let fs = view.state == Window.WINDOW_FULL_SCREEN;
|
||||
let el = $("#fullscreen");
|
||||
if (el) el.classList.toggle("active", fs);
|
||||
el = $("#maximize");
|
||||
if (el) {
|
||||
el.state.disabled = fs;
|
||||
el.state.disabled = fs; // TODO TEST
|
||||
}
|
||||
if (fs) {
|
||||
$(header).style.set {
|
||||
display: "none",
|
||||
};
|
||||
$("header").style.setProperty("display","none");
|
||||
}
|
||||
}
|
||||
|
||||
var header;
|
||||
var old_window_state = View.WINDOW_SHOWN;
|
||||
export var header;
|
||||
var old_window_state = Window.WINDOW_SHOWN;
|
||||
var input_blocked;
|
||||
|
||||
class Header: Reactor.Component {
|
||||
function this() {
|
||||
class Header extends Element {
|
||||
this() {
|
||||
header = this;
|
||||
}
|
||||
|
||||
function render() {
|
||||
var icon_conn;
|
||||
var title_conn;
|
||||
render() {
|
||||
let icon_conn;
|
||||
let title_conn;
|
||||
if (this.secure_connection && this.direct_connection) {
|
||||
icon_conn = svg_secure;
|
||||
title_conn = translate("Direct and encrypted connection");
|
||||
@ -82,95 +84,96 @@ class Header: Reactor.Component {
|
||||
icon_conn = svg_insecure_relay;
|
||||
title_conn = translate("Relayed and unencrypted connection");
|
||||
}
|
||||
var title = get_id();
|
||||
let title = get_id();
|
||||
if (pi.hostname) title += "(" + pi.username + "@" + pi.hostname + ")";
|
||||
if ((pi.displays || []).length == 0) {
|
||||
return <div .ellipsis style="size:*;text-align:center;margin:*;">{title}</div>;
|
||||
return (<div class="ellipsis" style="size:*;text-align:center;margin:*;">{title}</div>);
|
||||
}
|
||||
var screens = pi.displays.map(function(d, i) {
|
||||
return <div #screen class={pi.current_display == i ? "current" : ""}>
|
||||
let screens = pi.displays.map(function(d, i) {
|
||||
return <div id="screen" class={pi.current_display == i ? "current" : ""}>
|
||||
{i+1}
|
||||
</div>;
|
||||
});
|
||||
updateWindowToolbarPosition();
|
||||
var style = "flow:horizontal;";
|
||||
let style = "flow:horizontal;";
|
||||
if (is_osx) style += "margin:*";
|
||||
self.timer(1ms, toggleMenuState);
|
||||
return <div style={style}>
|
||||
{is_osx || is_xfce ? "" : <span #fullscreen>{svg_fullscreen}</span>}
|
||||
<div #screens>
|
||||
<span #secure title={title_conn}>{icon_conn}</span>
|
||||
<div .remote-id>{get_id()}</div>
|
||||
setTimeout(toggleMenuState,1);
|
||||
|
||||
return (<div style={style}>
|
||||
{is_osx || is_xfce ? "" : <span id="fullscreen">{svg_fullscreen}</span>}
|
||||
<div id="screens">
|
||||
<span id="secure" title={title_conn}>{icon_conn}</span>
|
||||
<div class="remote-id">{get_id()}</div>
|
||||
<div style="flow:horizontal;border-spacing: 0.5em;">{screens}</div>
|
||||
{this.renderGlobalScreens()}
|
||||
</div>
|
||||
<span #chat>{svg_chat}</span>
|
||||
<span #action>{svg_action}</span>
|
||||
<span #display>{svg_display}</span>
|
||||
<span id="chat">{svg_chat}</span>
|
||||
<span id="action">{svg_action}</span>
|
||||
<span id="display">{svg_display}</span>
|
||||
{this.renderDisplayPop()}
|
||||
{this.renderActionPop()}
|
||||
</div>;
|
||||
}
|
||||
</div>);
|
||||
}
|
||||
|
||||
function renderDisplayPop() {
|
||||
return <popup>
|
||||
<menu.context #display-options>
|
||||
<li #adjust-window style="display:none">{translate('Adjust Window')}</li>
|
||||
<div #adjust-window .separator style="display:none"/>
|
||||
<li #original type="view-style"><span>{svg_checkmark}</span>{translate('Original')}</li>
|
||||
<li #shrink type="view-style"><span>{svg_checkmark}</span>{translate('Shrink')}</li>
|
||||
<li #stretch type="view-style"><span>{svg_checkmark}</span>{translate('Stretch')}</li>
|
||||
<div .separator />
|
||||
<li #best type="image-quality"><span>{svg_checkmark}</span>{translate('Good image quality')}</li>
|
||||
<li #balanced type="image-quality"><span>{svg_checkmark}</span>{translate('Balanced')}</li>
|
||||
<li #low type="image-quality"><span>{svg_checkmark}</span>{translate('Optimize reaction time')}</li>
|
||||
<li #custom type="image-quality"><span>{svg_checkmark}</span>{translate('Custom')}</li>
|
||||
<div .separator />
|
||||
<li #show-remote-cursor .toggle-option><span>{svg_checkmark}</span>{translate('Show remote cursor')}</li>
|
||||
{audio_enabled ? <li #disable-audio .toggle-option><span>{svg_checkmark}</span>{translate('Mute')}</li> : ""}
|
||||
{keyboard_enabled && clipboard_enabled ? <li #disable-clipboard .toggle-option><span>{svg_checkmark}</span>{translate('Disable clipboard')}</li> : ""}
|
||||
{keyboard_enabled ? <li #lock-after-session-end .toggle-option><span>{svg_checkmark}</span>{translate('Lock after session end')}</li> : ""}
|
||||
{false && pi.platform == "Windows" ? <li #privacy-mode .toggle-option><span>{svg_checkmark}</span>{translate('Privacy mode')}</li> : ""}
|
||||
renderDisplayPop() {
|
||||
return (<popup>
|
||||
<menu class="context" id="display-options">
|
||||
<li id="adjust-window" style="display:none">{translate('Adjust Window')}</li>
|
||||
<div id="adjust-window" class="separator" style="display:none"/>
|
||||
<li id="original" type="view-style"><span>{svg_checkmark}</span>{translate('Original')}</li>
|
||||
<li id="shrink" type="view-style"><span>{svg_checkmark}</span>{translate('Shrink')}</li>
|
||||
<li id="stretch" type="view-style"><span>{svg_checkmark}</span>{translate('Stretch')}</li>
|
||||
<div class="separator" />
|
||||
<li id="best" type="image-quality"><span>{svg_checkmark}</span>{translate('Good image quality')}</li>
|
||||
<li id="balanced" type="image-quality"><span>{svg_checkmark}</span>{translate('Balanced')}</li>
|
||||
<li id="low" type="image-quality"><span>{svg_checkmark}</span>{translate('Optimize reaction time')}</li>
|
||||
<li id="custom" type="image-quality"><span>{svg_checkmark}</span>{translate('Custom')}</li>
|
||||
<div class="separator" />
|
||||
<li id="show-remote-cursor" class="toggle-option"><span>{svg_checkmark}</span>{translate('Show remote cursor')}</li>
|
||||
{audio_enabled ? <li id="disable-audio" class="toggle-option"><span>{svg_checkmark}</span>{translate('Mute')}</li> : ""}
|
||||
{keyboard_enabled && clipboard_enabled ? <li id="disable-clipboard" class="toggle-option"><span>{svg_checkmark}</span>{translate('Disable clipboard')}</li> : ""}
|
||||
{keyboard_enabled ? <li id="lock-after-session-end" class="toggle-option"><span>{svg_checkmark}</span>{translate('Lock after session end')}</li> : ""}
|
||||
{false && pi.platform == "Windows" ? <li id="privacy-mode" class="toggle-option"><span>{svg_checkmark}</span>{translate('Privacy mode')}</li> : ""}
|
||||
</menu>
|
||||
</popup>;
|
||||
</popup>);
|
||||
}
|
||||
|
||||
function renderActionPop() {
|
||||
return <popup>
|
||||
<menu.context #action-options>
|
||||
<li #transfer-file>{translate('Transfer File')}</li>
|
||||
<li #tunnel>{translate('TCP Tunneling')}</li>
|
||||
<div .separator />
|
||||
{keyboard_enabled && (pi.platform == "Linux" || pi.sas_enabled) ? <li #ctrl-alt-del>{translate('Insert')} Ctrl + Alt + Del</li> : ""}
|
||||
<div .separator />
|
||||
{keyboard_enabled ? <li #lock-screen>{translate('Insert Lock')}</li> : ""}
|
||||
{false && pi.platform == "Windows" ? <li #block-input>Block user input </li> : ""}
|
||||
{handler.support_refresh() ? <li #refresh>{translate('Refresh')}</li> : ""}
|
||||
renderActionPop() {
|
||||
return (<popup>
|
||||
<menu class="context" id="action-options">
|
||||
<li id="transfer-file">{translate('Transfer File')}</li>
|
||||
<li id="tunnel">{translate('TCP Tunneling')}</li>
|
||||
<div class="separator" />
|
||||
{keyboard_enabled && (pi.platform == "Linux" || pi.sas_enabled) ? <li id="ctrl-alt-del">{translate('Insert')} Ctrl + Alt + Del</li> : ""}
|
||||
<div class="separator" />
|
||||
{keyboard_enabled ? <li id="lock-screen">{translate('Insert Lock')}</li> : ""}
|
||||
{false && pi.platform == "Windows" ? <li id="block-input">Block user input </li> : ""}
|
||||
{handler.support_refresh() ? <li id="refresh">{translate('Refresh')}</li> : ""}
|
||||
</menu>
|
||||
</popup>;
|
||||
</popup>);
|
||||
}
|
||||
|
||||
function renderGlobalScreens() {
|
||||
renderGlobalScreens() {
|
||||
if (pi.displays.length < 3) return "";
|
||||
var x0 = 9999999;
|
||||
var y0 = 9999999;
|
||||
var x = -9999999;
|
||||
var y = -9999999;
|
||||
let x0 = 9999999;
|
||||
let y0 = 9999999;
|
||||
let x = -9999999;
|
||||
let y = -9999999;
|
||||
pi.displays.map(function(d, i) {
|
||||
if (d.x < x0) x0 = d.x;
|
||||
if (d.y < y0) y0 = d.y;
|
||||
var dx = d.x + d.width;
|
||||
let dx = d.x + d.width;
|
||||
if (dx > x) x = dx;
|
||||
var dy = d.y + d.height;
|
||||
let dy = d.y + d.height;
|
||||
if (dy > y) y = dy;
|
||||
});
|
||||
var w = x - x0;
|
||||
var h = y - y0;
|
||||
var scale = 16. / h;
|
||||
var screens = pi.displays.map(function(d, i) {
|
||||
var min_wh = d.width > d.height ? d.height : d.width;
|
||||
var fs = min_wh * 0.9 * scale;
|
||||
var style = "width:" + (d.width * scale) + "px;" +
|
||||
let w = x - x0;
|
||||
let h = y - y0;
|
||||
let scale = 16. / h;
|
||||
let screens = pi.displays.map(function(d, i) {
|
||||
let min_wh = d.width > d.height ? d.height : d.width;
|
||||
let fs = min_wh * 0.9 * scale;
|
||||
let style = "width:" + (d.width * scale) + "px;" +
|
||||
"height:" + (d.height * scale) + "px;" +
|
||||
"left:" + ((d.x - x0) * scale) + "px;" +
|
||||
"top:" + ((d.y - y0) * scale) + "px;" +
|
||||
@ -181,91 +184,91 @@ class Header: Reactor.Component {
|
||||
return <div style={style} class={pi.current_display == i ? "current" : ""}>{i+1}</div>;
|
||||
});
|
||||
|
||||
var style = "width:" + (w * scale) + "px; height:" + (h * scale) + "px;";
|
||||
return <div #global-screens style={style}>
|
||||
let style = "width:" + (w * scale) + "px; height:" + (h * scale) + "px;";
|
||||
return <div id="global-screens" style={style}>
|
||||
{screens}
|
||||
</div>;
|
||||
}
|
||||
|
||||
event click $(#fullscreen) (_, el) {
|
||||
if (view.windowState == View.WINDOW_FULL_SCREEN) {
|
||||
if (old_window_state == View.WINDOW_MAXIMIZED) {
|
||||
view.windowState = View.WINDOW_SHOWN;
|
||||
["on click at #fullscreen"](_, el) {
|
||||
if (view.state == Window.WINDOW_FULL_SCREEN) {
|
||||
if (old_window_state == Window.WINDOW_MAXIMIZED) {
|
||||
view.state = Window.WINDOW_SHOWN;
|
||||
}
|
||||
view.windowState = old_window_state;
|
||||
view.state = old_window_state;
|
||||
} else {
|
||||
old_window_state = view.windowState;
|
||||
if (view.windowState == View.WINDOW_MAXIMIZED) {
|
||||
view.windowState = View.WINDOW_SHOWN;
|
||||
old_window_state = view.state;
|
||||
if (view.state == Window.WINDOW_MAXIMIZED) {
|
||||
view.state = Window.WINDOW_SHOWN;
|
||||
}
|
||||
view.windowState = View.WINDOW_FULL_SCREEN;
|
||||
if (is_linux) { self.timer(150ms, function() { view.windowState = View.WINDOW_FULL_SCREEN; }); }
|
||||
view.state = Window.WINDOW_FULL_SCREEN;
|
||||
if (is_linux) { setTimeout(()=>view.state = Window.WINDOW_FULL_SCREEN,150); }
|
||||
}
|
||||
}
|
||||
|
||||
event click $(#chat) {
|
||||
["on click at #chat"]() {
|
||||
startChat();
|
||||
}
|
||||
|
||||
event click $(#action) (_, me) {
|
||||
var menu = $(menu#action-options);
|
||||
["on click at #action"](_, me) {
|
||||
let menu = $("menu#action-options");
|
||||
me.popup(menu);
|
||||
}
|
||||
|
||||
event click $(#display) (_, me) {
|
||||
var menu = $(menu#display-options);
|
||||
["on click at #display"](_, me) {
|
||||
let menu = $("menu#display-options");
|
||||
me.popup(menu);
|
||||
}
|
||||
|
||||
event click $(#screen) (_, me) {
|
||||
["on click at #screen"](_, me) {
|
||||
if (pi.current_display == me.index) return;
|
||||
handler.switch_display(me.index);
|
||||
handler.xcall("switch_display",me.index);
|
||||
}
|
||||
|
||||
event click $(#transfer-file) {
|
||||
handler.transfer_file();
|
||||
["on click at #transfer-file"]() {
|
||||
handler.xcall("transfer_file");
|
||||
}
|
||||
|
||||
event click $(#tunnel) {
|
||||
handler.tunnel();
|
||||
["on click at #tunnel"] () {
|
||||
handler.xcall("tunnel");
|
||||
}
|
||||
|
||||
event click $(#ctrl-alt-del) {
|
||||
handler.ctrl_alt_del();
|
||||
["on click at #ctrl-alt-del"]() {
|
||||
handler.xcall("ctrl_alt_del");
|
||||
}
|
||||
|
||||
event click $(#lock-screen) {
|
||||
handler.lock_screen();
|
||||
["on click at #lock-screen"]() {
|
||||
handler.xcall("lock_screen");
|
||||
}
|
||||
|
||||
event click $(#refresh) {
|
||||
handler.refresh_video();
|
||||
["on click at #refresh"] () {
|
||||
handler.xcall("refresh_video");
|
||||
}
|
||||
|
||||
event click $(#block-input) {
|
||||
["on click at #block-input"] (_,me) {
|
||||
if (!input_blocked) {
|
||||
handler.toggle_option("block-input");
|
||||
handler.xcall("toggle_option","block-input");
|
||||
input_blocked = true;
|
||||
$(#block-input).text = "Unblock user input";
|
||||
me.text = "Unblock user input"; // TEST
|
||||
} else {
|
||||
handler.toggle_option("unblock-input");
|
||||
handler.xcall("toggle_option","unblock-input");
|
||||
input_blocked = false;
|
||||
$(#block-input).text = "Block user input";
|
||||
me.text = "Block user input";
|
||||
}
|
||||
}
|
||||
|
||||
event click $(menu#display-options>li) (_, me) {
|
||||
["on click at menu#display-options>li"] (_, me) {
|
||||
if (me.id == "custom") {
|
||||
handle_custom_image_quality();
|
||||
} else if (me.attributes.hasClass("toggle-option")) {
|
||||
handler.toggle_option(me.id);
|
||||
toggleMenuState();
|
||||
} else if (!me.attributes.hasClass("selected")) {
|
||||
var type = me.attributes["type"];
|
||||
let type = me.attributes["type"];
|
||||
if (type == "image-quality") {
|
||||
handler.save_image_quality(me.id);
|
||||
handler.xcall("save_image_quality",me.id);
|
||||
} else if (type == "view-style") {
|
||||
handler.save_view_style(me.id);
|
||||
handler.xcall("save_view_style",me.id);
|
||||
adaptDisplay();
|
||||
}
|
||||
toggleMenuState();
|
||||
@ -274,96 +277,90 @@ class Header: Reactor.Component {
|
||||
}
|
||||
|
||||
function handle_custom_image_quality() {
|
||||
var tmp = handler.get_custom_image_quality();
|
||||
var bitrate0 = tmp[0] || 50;
|
||||
var quantizer0 = tmp.length > 1 ? tmp[1] : 100;
|
||||
let tmp = handler.xcall("get_custom_image_quality");
|
||||
let bitrate0 = tmp[0] || 50;
|
||||
let quantizer0 = tmp.length > 1 ? tmp[1] : 100;
|
||||
msgbox("custom", "Custom Image Quality", "<div .form> \
|
||||
<div><input type=\"hslider\" style=\"width: 50%\" name=\"bitrate\" max=\"100\" min=\"10\" value=\"" + bitrate0 + "\"/ buddy=\"bitrate-buddy\"><b #bitrate-buddy>x</b>% bitrate</div> \
|
||||
<div><input type=\"hslider\" style=\"width: 50%\" name=\"quantizer\" max=\"100\" min=\"0\" value=\"" + quantizer0 + "\"/ buddy=\"quantizer-buddy\"><b #quantizer-buddy>x</b>% quantizer</div> \
|
||||
</div>", function(res=null) {
|
||||
if (!res) return;
|
||||
if (!res.bitrate) return;
|
||||
handler.save_custom_image_quality(res.bitrate, res.quantizer);
|
||||
handler.xcall("save_custom_image_quality",res.bitrate, res.quantizer);
|
||||
toggleMenuState();
|
||||
});
|
||||
}
|
||||
|
||||
function toggleMenuState() {
|
||||
var values = [];
|
||||
var q = handler.get_image_quality();
|
||||
let values = [];
|
||||
let q = handler.xcall("get_image_quality");
|
||||
if (!q) q = "balanced";
|
||||
values.push(q);
|
||||
var s = handler.get_view_style();
|
||||
let s = handler.xcall("get_view_style");
|
||||
if (!s) s = "original";
|
||||
values.push(s);
|
||||
for (var el in $$(menu#display-options>li)) {
|
||||
el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0);
|
||||
for (let el in $$("menu#display-options>li")) {
|
||||
el.classList.toggle("selected", values.indexOf(el.id) >= 0);
|
||||
}
|
||||
for (var id in ["show-remote-cursor", "disable-audio", "disable-clipboard", "lock-after-session-end", "privacy-mode"]) {
|
||||
var el = self.select('#' + id);
|
||||
for (let id in ["show-remote-cursor", "disable-audio", "disable-clipboard", "lock-after-session-end", "privacy-mode"]) {
|
||||
let el = $('#' + id); // TEST
|
||||
if (el) {
|
||||
el.attributes.toggleClass("selected", handler.get_toggle_option(id));
|
||||
el.classList.toggle("selected", handler.xcall("get_toggle_option",id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_osx) {
|
||||
$(header).content(<Header />);
|
||||
$(header).attributes["role"] = "window-caption";
|
||||
$("header").content(<Header />);
|
||||
$("header").attributes["role"] = "window-caption"; // TODO
|
||||
} else {
|
||||
if (is_file_transfer || is_port_forward) {
|
||||
$(caption).content(<Header />);
|
||||
$("caption").content(<Header />);
|
||||
} else {
|
||||
$(div.window-toolbar).content(<Header />);
|
||||
$("div.window-toolbar").content(<Header />);
|
||||
}
|
||||
setWindowButontsAndIcon();
|
||||
}
|
||||
|
||||
if (!(is_file_transfer || is_port_forward)) {
|
||||
$(header).style.set {
|
||||
height: "32px",
|
||||
};
|
||||
$("header").style.setProperty("height","32px");
|
||||
if (!is_osx) {
|
||||
$(div.window-icon).style.set {
|
||||
size: "32px",
|
||||
};
|
||||
$("div.window-icon").style.setProperty("size","32px");
|
||||
}
|
||||
}
|
||||
|
||||
handler.updatePi = function(v) {
|
||||
pi = v;
|
||||
header.update();
|
||||
header.componentUpdate();
|
||||
if (is_port_forward) {
|
||||
view.windowState = View.WINDOW_MINIMIZED;
|
||||
view.state = Window.WINDOW_MINIMIZED;
|
||||
}
|
||||
}
|
||||
|
||||
handler.switchDisplay = function(i) {
|
||||
pi.current_display = i;
|
||||
header.update();
|
||||
header.componentUpdate();
|
||||
}
|
||||
|
||||
function updateWindowToolbarPosition() {
|
||||
if (is_osx) return;
|
||||
self.timer(1ms, function() {
|
||||
var el = $(div.window-toolbar);
|
||||
var w1 = el.box(#width, #border);
|
||||
var w2 = $(header).box(#width, #border);
|
||||
var x = (w2 - w1) / 2;
|
||||
el.style.set {
|
||||
left: x + "px",
|
||||
display: "block",
|
||||
};
|
||||
});
|
||||
setTimeout(function() {
|
||||
let el = $("div.window-toolbar");
|
||||
let w1 = el.state.box("width", "border"); // TEST
|
||||
let w2 = $("header").state.box("width", "border");
|
||||
let x = (w2 - w1) / 2;
|
||||
el.style.setProperty("left",x + "px");
|
||||
el.style.setProperty("display","block")
|
||||
},1);
|
||||
}
|
||||
|
||||
view.on("size", function() {
|
||||
view.onsizechange = function() {
|
||||
// ensure size is done, so add timer
|
||||
self.timer(1ms, function() {
|
||||
setTimeout(function() {
|
||||
updateWindowToolbarPosition();
|
||||
adaptDisplay();
|
||||
});
|
||||
});
|
||||
},1);
|
||||
};
|
||||
|
||||
handler.newMessage = function(text) {
|
||||
chat_msgs.push({text: text, name: pi.username || "", time: getNowStr()});
|
||||
@ -372,25 +369,25 @@ handler.newMessage = function(text) {
|
||||
|
||||
function sendMsg(text) {
|
||||
chat_msgs.push({text: text, name: "me", time: getNowStr()});
|
||||
handler.send_chat(text);
|
||||
handler.xcall("send_chat",text);
|
||||
if (chatbox) chatbox.refresh();
|
||||
}
|
||||
|
||||
var chatbox;
|
||||
function startChat() {
|
||||
if (chatbox) {
|
||||
chatbox.windowState = View.WINDOW_SHOWN;
|
||||
chatbox.refresh();
|
||||
chatbox.state = Window.WINDOW_SHOWN; // TODO TEST el.state
|
||||
chatbox.refresh(); // TODO el.refresh
|
||||
return;
|
||||
}
|
||||
var icon = handler.get_icon();
|
||||
var (sx, sy, sw, sh) = view.screenBox(#workarea, #rectw);
|
||||
var w = 300;
|
||||
var h = 400;
|
||||
var x = (sx + sw - w) / 2;
|
||||
var y = sy + 80;
|
||||
var params = {
|
||||
type: View.FRAME_WINDOW,
|
||||
let icon = handler.xcall("get_icon");
|
||||
let [sx, sy, sw, sh] = view.screenBox("workarea", "rectw"); // TEST
|
||||
let w = 300;
|
||||
let h = 400;
|
||||
let x = (sx + sw - w) / 2;
|
||||
let y = sy + 80;
|
||||
let params = {
|
||||
type: Window.FRAME_WINDOW,
|
||||
x: x,
|
||||
y: y,
|
||||
width: w,
|
||||
@ -399,14 +396,15 @@ function startChat() {
|
||||
parameters: { msgs: chat_msgs, callback: sendMsg, icon: icon },
|
||||
caption: get_id(),
|
||||
};
|
||||
var html = handler.get_chatbox();
|
||||
let html = handler.xcall("get_chatbox");
|
||||
if (html) params.html = html;
|
||||
else params.url = self.url("chatbox.html");
|
||||
chatbox = view.window(params);
|
||||
else params.url = document.url("chatbox.html");
|
||||
chatbox = view.window(params); // TEST
|
||||
}
|
||||
|
||||
handler.setConnectionType = function(secured, direct) {
|
||||
header.update({
|
||||
// TEST
|
||||
header.componentUpdate({
|
||||
secure_connection: secured,
|
||||
direct_connection: direct,
|
||||
});
|
||||
|
@ -1,30 +1,32 @@
|
||||
class PortForward: Reactor.Component {
|
||||
function render() {
|
||||
var args = handler.get_args();
|
||||
var is_rdp = handler.is_rdp();
|
||||
import { translate } from "./common.js";
|
||||
|
||||
class PortForward extends Element {
|
||||
render() {
|
||||
let args = handler.xcall("get_args");
|
||||
let is_rdp = handler.xcall("is_rdp");
|
||||
if (is_rdp) {
|
||||
this.pfs = [["", "", "RDP"]];
|
||||
args = ["rdp"];
|
||||
} else if (args.length) {
|
||||
this.pfs = [args];
|
||||
} else {
|
||||
this.pfs = handler.get_port_forwards();
|
||||
this.pfs = handler.xcall("get_port_forwards");
|
||||
}
|
||||
var pfs = this.pfs.map(function(pf, i) {
|
||||
return <tr key={i} .value>
|
||||
<td>{is_rdp ? <button .button #new-rdp>New RDP</button> : pf[0]}</td>
|
||||
<td .right-arrow style="text-align: center; padding-left: 0">{args.length ? svg_arrow : ""}</td>
|
||||
let pfs = this.pfs.map(function(pf, i) {
|
||||
return (<tr key={i} class="value">
|
||||
<td>{is_rdp ? <button class="button" id="new-rdp">New RDP</button> : pf[0]}</td>
|
||||
<td class="right-arrow" style="text-align: center; padding-left: 0">{args.length ? svg_arrow : ""}</td>
|
||||
<td>{pf[1] || "localhost"}</td>
|
||||
<td>{pf[2]}</td>
|
||||
{args.length ? "" : <td .remove>{svg_cancel}</td>}
|
||||
</tr>;
|
||||
{args.length ? "" : <td class="remove">{svg_cancel}</td>}
|
||||
</tr>);
|
||||
});
|
||||
return <div #file-transfer><section>
|
||||
return <div id="file-transfer"><section>
|
||||
{pfs.length ? <div style="background: green; color: white; text-align: center; padding: 0.5em;">
|
||||
<span style="font-size: 1.2em">{translate('Listening ...')}</span><br/>
|
||||
<span style="font-size: 0.8em; color: #ddd">{translate('not_close_tcp_tip')}</span>
|
||||
</div> : ""}
|
||||
<table #port-forward>
|
||||
<table id="port-forward">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{translate('Local Port')}</th>
|
||||
@ -37,11 +39,11 @@ class PortForward: Reactor.Component {
|
||||
<tbody key={pfs.length}>
|
||||
{args.length ? "" :
|
||||
<tr>
|
||||
<td><input|number #port /></td>
|
||||
<td .right-arrow style="text-align: center">{svg_arrow}</td>
|
||||
<td><input|text #remote-host novalue="localhost" /></td>
|
||||
<td><input|number #remote-port /></td>
|
||||
<td style="margin:0;"><button .button #add>{translate('Add')}</button></td>
|
||||
<td><input type="number" id="port" /></td>
|
||||
<td class="right-arrow" style="text-align: center">{svg_arrow}</td>
|
||||
<td><input type="text" id="remote-host" novalue="localhost" /></td>
|
||||
<td><input type="number" id="remote-port" /></td>
|
||||
<td style="margin:0;"><button class="button" id="add">{translate('Add')}</button></td>
|
||||
</tr>
|
||||
}
|
||||
{pfs}
|
||||
@ -49,29 +51,30 @@ class PortForward: Reactor.Component {
|
||||
</table></section></div>;
|
||||
}
|
||||
|
||||
event click $(#add) () {
|
||||
var port = ($(#port).value || "").toInteger() || 0;
|
||||
var remote_host = $(#remote-host).value || "";
|
||||
var remote_port = ($(#remote-port).value || "").toInteger() || 0;
|
||||
["on click at #add"] () {
|
||||
let port = ($("#port").value || "").toInteger() || 0; // TODO toInteger
|
||||
let remote_host = $("#remote-host").value || "";
|
||||
let remote_port = ($("#remote-port").value || "").toInteger() || 0; // TODO toInteger
|
||||
if (port <= 0 || remote_port <= 0) return;
|
||||
handler.add_port_forward(port, remote_host, remote_port);
|
||||
this.update();
|
||||
handler.xcall("add_port_forward",port, remote_host, remote_port);
|
||||
this.componentUpdate();
|
||||
}
|
||||
|
||||
event click $(#new-rdp) {
|
||||
handler.new_rdp();
|
||||
["on click at #new-rdp"] () {
|
||||
handler.xcall("new_rdp");
|
||||
}
|
||||
|
||||
event click $(.remove svg) (_, me) {
|
||||
var pf = this.pfs[me.parent.parent.index - 1];
|
||||
handler.remove_port_forward(pf[0]);
|
||||
this.update();
|
||||
["on click at .remove svg"](_, me) {
|
||||
let pf = this.pfs[me.parentElement.parentElement.index - 1];
|
||||
handler.xcall("remove_port_forward",pf[0]);
|
||||
this.componentUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
function initializePortForward()
|
||||
export function initializePortForward()
|
||||
{
|
||||
$(#file-transfer-wrapper).content(<PortForward />);
|
||||
$(#video-wrapper).style.set { visibility: "hidden", position: "absolute" };
|
||||
$(#file-transfer-wrapper).style.set { display: "block" };
|
||||
$("#file-transfer-wrapper").content(<PortForward />);
|
||||
$("#video-wrapper").style.setProperty("visibility","hidden");
|
||||
$("#video-wrapper").style.setProperty("position","absolute")
|
||||
$("#file-transfer-wrapper").style.setProperty("display","block");
|
||||
}
|
||||
|
@ -1,19 +1,24 @@
|
||||
<html window-resizable window-frame="extended">
|
||||
<head>
|
||||
<style>
|
||||
<link rel="stylesheet" href="common.css">
|
||||
<link rel="stylesheet" href="remote.css">
|
||||
<link rel="stylesheet" href="file_transfer.css">
|
||||
<link rel="stylesheet" href="header.css">
|
||||
<!-- <style>
|
||||
@import url(common.css);
|
||||
@import url(remote.css);
|
||||
@import url(file_transfer.css);
|
||||
@import url(header.css);
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
</style> -->
|
||||
<script type="module" src="remote.js"></script>
|
||||
<!-- <script type="text/tiscript">
|
||||
include "common.tis";
|
||||
include "remote.tis";
|
||||
include "file_transfer.tis";
|
||||
include "port_forward.tis";
|
||||
include "grid.tis";
|
||||
include "header.tis";
|
||||
</script>
|
||||
</script> -->
|
||||
</head>
|
||||
<header>
|
||||
<div.window-icon role="window-icon"><icon /></div>
|
||||
|
544
src/ui/remote.js
544
src/ui/remote.js
@ -1,7 +1,13 @@
|
||||
var cursor_img = $(img#cursor);
|
||||
import { $ } from "@sciter";
|
||||
import { handler,view,is_file_transfer,isReasonableSize,msgbox,is_osx, is_linux, centerize, connecting } from "./common.js";
|
||||
import { initializeFileTransfer, save_file_transfer_close_state } from "./file_transfer.js";
|
||||
import { initializePortForward } from "./port_forward.js";
|
||||
import { header } from "./header.js";
|
||||
|
||||
var cursor_img = $("img#cursor");
|
||||
var last_key_time = 0;
|
||||
is_file_transfer = handler.is_file_transfer();
|
||||
var is_port_forward = handler.is_port_forward();
|
||||
is_file_transfer = handler.xcall("is_file_transfer");
|
||||
export var is_port_forward = handler.xcall("is_port_forward");
|
||||
var display_width = 0;
|
||||
var display_height = 0;
|
||||
var display_origin_x = 0;
|
||||
@ -20,40 +26,42 @@ handler.setDisplay = function(x, y, w, h) {
|
||||
adaptDisplay();
|
||||
}
|
||||
|
||||
function adaptDisplay() {
|
||||
var w = display_width;
|
||||
var h = display_height;
|
||||
export function adaptDisplay() {
|
||||
let w = display_width;
|
||||
let h = display_height;
|
||||
if (!w || !h) return;
|
||||
var style = handler.get_view_style();
|
||||
let style = handler.xcall("get_view_style");
|
||||
display_scale = 1.;
|
||||
var (sx, sy, sw, sh) = view.screenBox(view.windowState == View.WINDOW_FULL_SCREEN ? #frame : #workarea, #rectw);
|
||||
let [sx, sy, sw, sh] = view.screenBox(view.state == Window.WINDOW_FULL_SCREEN ? "frame" : "workarea", "rectw");
|
||||
if (sw >= w && sh > h) {
|
||||
var hh = $(header).box(#height, #border);
|
||||
var el = $(div#adjust-window);
|
||||
let hh = $("header").state.box("height", "border");
|
||||
let el = $("div#adjust-window");
|
||||
if (sh > h + hh && el) {
|
||||
el.style.set{ display: "block" };
|
||||
el = $(li#adjust-window);
|
||||
el.style.set{ display: "block" };
|
||||
el.onClick = function() {
|
||||
view.windowState == View.WINDOW_SHOWN;
|
||||
var (x, y) = view.box(#position, #border, #screen);
|
||||
el.style.setProperty("display","block");
|
||||
el = $("li#adjust-window");
|
||||
el.style.setProperty("display","block");
|
||||
el.on("click",function() {
|
||||
// TODO old:view.state == Window.WINDOW_SHOWN;
|
||||
view.state = Window.WINDOW_SHOWN;
|
||||
let [x, y] = view.state.box("position", "border", "screen");
|
||||
// extra for border
|
||||
var extra = 2;
|
||||
let extra = 2;
|
||||
view.move(x, y, w + extra, h + hh + extra);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if (style != "original") {
|
||||
var bw = $(body).box(#width, #border);
|
||||
var bh = $(body).box(#height, #border);
|
||||
if (view.windowState == View.WINDOW_FULL_SCREEN) {
|
||||
let bw = $("body").state.box("width", "border");
|
||||
let bh = $("body").state.box("height", "border");
|
||||
if (view.state == Window.WINDOW_FULL_SCREEN) {
|
||||
bw = sw;
|
||||
bh = sh;
|
||||
}
|
||||
if (bw > 0 && bh > 0) {
|
||||
var scale_x = bw.toFloat() / w;
|
||||
var scale_y = bh.toFloat() / h;
|
||||
var scale = scale_x < scale_y ? scale_x : scale_y;
|
||||
// TEST del toFloat()
|
||||
let scale_x = bw / w;
|
||||
let scale_y = bh / h;
|
||||
let scale = scale_x < scale_y ? scale_x : scale_y;
|
||||
if ((scale > 1 && style == "stretch") ||
|
||||
(scale < 1 && style == "shrink")) {
|
||||
display_scale = scale;
|
||||
@ -62,10 +70,8 @@ function adaptDisplay() {
|
||||
}
|
||||
}
|
||||
}
|
||||
handler.style.set {
|
||||
width: w + "px",
|
||||
height: h + "px",
|
||||
};
|
||||
handler.style.setProperty("width",w + "px");
|
||||
handler.style.setProperty("height",h + "px")
|
||||
}
|
||||
|
||||
// https://sciter.com/event-handling/
|
||||
@ -73,44 +79,45 @@ function adaptDisplay() {
|
||||
|
||||
var entered = false;
|
||||
|
||||
var keymap = {};
|
||||
for (var (k, v) in Event) {
|
||||
k = k + ""
|
||||
if (k[0] == "V" && k[1] == "K") {
|
||||
keymap[v] = k;
|
||||
}
|
||||
}
|
||||
// TODO !
|
||||
// var keymap = {};
|
||||
// for (var (k, v) in Event) {
|
||||
// k = k + ""
|
||||
// if (k[0] == "V" && k[1] == "K") {
|
||||
// keymap[v] = k;
|
||||
// }
|
||||
// }
|
||||
|
||||
// VK_ENTER = VK_RETURN
|
||||
// somehow, handler.onKey and view.onKey not working
|
||||
function self.onKey(evt) {
|
||||
last_key_time = getTime();
|
||||
if (is_file_transfer || is_port_forward) return false;
|
||||
if (!entered) return false;
|
||||
if (!keyboard_enabled) return false;
|
||||
switch (evt.type) {
|
||||
case Event.KEY_DOWN:
|
||||
handler.key_down_or_up(1, keymap[evt.keyCode] || "", evt.keyCode, evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
if (is_osx && evt.commandKey) {
|
||||
handler.key_down_or_up(0, keymap[evt.keyCode] || "", evt.keyCode, evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
}
|
||||
break;
|
||||
case Event.KEY_UP:
|
||||
handler.key_down_or_up(0, keymap[evt.keyCode] || "", evt.keyCode, evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
break;
|
||||
case Event.KEY_CHAR:
|
||||
// the keypress event is fired when the element receives character value. Event.keyCode is a UNICODE code point of the character
|
||||
handler.key_down_or_up(2, "", evt.keyCode, evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// function self.onKey(evt) {
|
||||
// last_key_time = getTime();
|
||||
// if (is_file_transfer || is_port_forward) return false;
|
||||
// if (!entered) return false;
|
||||
// if (!keyboard_enabled) return false;
|
||||
// switch (evt.type) {
|
||||
// case Event.KEY_DOWN:
|
||||
// handler.key_down_or_up(1, keymap[evt.keyCode] || "", evt.keyCode, evt.altKey,
|
||||
// evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
// if (is_osx && evt.commandKey) {
|
||||
// handler.key_down_or_up(0, keymap[evt.keyCode] || "", evt.keyCode, evt.altKey,
|
||||
// evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
// }
|
||||
// break;
|
||||
// case Event.KEY_UP:
|
||||
// handler.key_down_or_up(0, keymap[evt.keyCode] || "", evt.keyCode, evt.altKey,
|
||||
// evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
// break;
|
||||
// case Event.KEY_CHAR:
|
||||
// // the keypress event is fired when the element receives character value. Event.keyCode is a UNICODE code point of the character
|
||||
// handler.key_down_or_up(2, "", evt.keyCode, evt.altKey,
|
||||
// evt.ctrlKey, evt.shiftKey, evt.commandKey, evt.extendedKey);
|
||||
// break;
|
||||
// default:
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
var wait_window_toolbar = false;
|
||||
var last_mouse_mask;
|
||||
@ -156,176 +163,177 @@ function accWheel(v, is_x) {
|
||||
} else {
|
||||
v = abs_v;
|
||||
}
|
||||
handler.send_mouse(3, is_x ? d : 0, !is_x ? d : 0, false, false, false, false);
|
||||
handler.xcall("send_mouse",3, is_x ? d : 0, !is_x ? d : 0, false, false, false, false);
|
||||
accWheel(v, is_x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handler.onMouse(evt)
|
||||
{
|
||||
if (is_file_transfer || is_port_forward) return false;
|
||||
if (view.windowState == View.WINDOW_FULL_SCREEN && !dragging) {
|
||||
var dy = evt.y - scroll_body.scroll(#top);
|
||||
if (dy <= 1) {
|
||||
if (!wait_window_toolbar) {
|
||||
wait_window_toolbar = true;
|
||||
self.timer(300ms, function() {
|
||||
if (!wait_window_toolbar) return;
|
||||
var extra = 0;
|
||||
// workaround for stupid Sciter, without this, click
|
||||
// event not triggered on top part of buttons on toolbar
|
||||
if (is_osx) extra = 10;
|
||||
if (view.windowState == View.WINDOW_FULL_SCREEN) {
|
||||
$(header).style.set {
|
||||
display: "block",
|
||||
padding: (2 * workarea_offset + extra) + "px 0 0 0",
|
||||
};
|
||||
}
|
||||
wait_window_toolbar = false;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
wait_window_toolbar = false;
|
||||
var h = $(header).style;
|
||||
if (dy > 20 && h#display != "none") {
|
||||
h.set {
|
||||
display: "none",
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!got_mouse_control) {
|
||||
if (Math.abs(evt.x - cur_local_x) > 12 || Math.abs(evt.y - cur_local_y) > 12) {
|
||||
got_mouse_control = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var mask = 0;
|
||||
var wheel_delta_x;
|
||||
var wheel_delta_y;
|
||||
switch(evt.type) {
|
||||
case Event.MOUSE_DOWN:
|
||||
mask = 1;
|
||||
dragging = true;
|
||||
break;
|
||||
case Event.MOUSE_UP:
|
||||
mask = 2;
|
||||
dragging = false;
|
||||
break;
|
||||
case Event.MOUSE_MOVE:
|
||||
if (cursor_img.style#display != "none" && keyboard_enabled) {
|
||||
cursor_img.style#display = "none";
|
||||
handler.style#cursor = '';
|
||||
}
|
||||
break;
|
||||
case Event.MOUSE_WHEEL:
|
||||
// mouseWheelDistance = 8 * [currentUserDefs floatForKey:@"com.apple.scrollwheel.scaling"];
|
||||
mask = 3;
|
||||
{
|
||||
var (dx, dy) = evt.wheelDeltas;
|
||||
if (dx > 0) dx = 1;
|
||||
else if (dx < 0) dx = -1;
|
||||
if (dy > 0) dy = 1;
|
||||
else if (dy < 0) dy = -1;
|
||||
if (Math.abs(dx) > Math.abs(dy)) {
|
||||
dy = 0;
|
||||
} else {
|
||||
dx = 0;
|
||||
}
|
||||
acc_wheel_delta_x += dx;
|
||||
acc_wheel_delta_y += dy;
|
||||
wheel_delta_x = acc_wheel_delta_x.toInteger();
|
||||
wheel_delta_y = acc_wheel_delta_y.toInteger();
|
||||
acc_wheel_delta_x -= wheel_delta_x;
|
||||
acc_wheel_delta_y -= wheel_delta_y;
|
||||
var now = getTime();
|
||||
var dt = last_wheel_time > 0 ? (now - last_wheel_time) / 1000 : 0;
|
||||
if (dt > 0) {
|
||||
var vx = dx / dt;
|
||||
var vy = dy / dt;
|
||||
if (vx != 0 || vy != 0) {
|
||||
inertia_velocity_x = vx;
|
||||
inertia_velocity_y = vy;
|
||||
}
|
||||
}
|
||||
acc_wheel_delta_x0 += dx;
|
||||
acc_wheel_delta_y0 += dy;
|
||||
total_wheel_time += dt;
|
||||
if (dx == 0 && dy == 0) {
|
||||
wheeling = false;
|
||||
if (dt < 0.1 && total_wheel_time > 0) {
|
||||
var v2 = (acc_wheel_delta_y0 / total_wheel_time) * inertia_velocity_y;
|
||||
if (v2 > 0) {
|
||||
v2 = Math.sqrt(v2);
|
||||
inertia_velocity_y = inertia_velocity_y < 0 ? -v2 : v2;
|
||||
accWheel(inertia_velocity_y, false);
|
||||
}
|
||||
v2 = (acc_wheel_delta_x0 / total_wheel_time) * inertia_velocity_x;
|
||||
if (v2 > 0) {
|
||||
v2 = Math.sqrt(v2);
|
||||
inertia_velocity_x = inertia_velocity_x < 0 ? -v2 : v2;
|
||||
accWheel(inertia_velocity_x, true);
|
||||
}
|
||||
}
|
||||
resetWheel();
|
||||
} else {
|
||||
wheeling = true;
|
||||
}
|
||||
last_wheel_time = now;
|
||||
if (wheel_delta_x == 0 && wheel_delta_y == 0) return keyboard_enabled;
|
||||
}
|
||||
break;
|
||||
case Event.MOUSE_DCLICK: // seq: down, up, dclick, up
|
||||
mask = 1;
|
||||
break;
|
||||
case Event.MOUSE_ENTER:
|
||||
entered = true;
|
||||
stdout.println("enter");
|
||||
return keyboard_enabled;
|
||||
case Event.MOUSE_LEAVE:
|
||||
entered = false;
|
||||
stdout.println("leave");
|
||||
return keyboard_enabled;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
var x = evt.x;
|
||||
var y = evt.y;
|
||||
if (mask != 0) {
|
||||
// to gain control of the mouse, user must move mouse
|
||||
if (cur_x != x || cur_y != y) {
|
||||
return keyboard_enabled;
|
||||
}
|
||||
// save bandwidth
|
||||
x = 0;
|
||||
y = 0;
|
||||
} else {
|
||||
cur_local_x = cur_x = x;
|
||||
cur_local_y = cur_y = y;
|
||||
}
|
||||
if (mask != 3) {
|
||||
resetWheel();
|
||||
}
|
||||
if (!keyboard_enabled) return false;
|
||||
x = (x / display_scale).toInteger();
|
||||
y = (y / display_scale).toInteger();
|
||||
// insert down between two up, osx has this behavior for triple click
|
||||
if (last_mouse_mask == 2 && mask == 2) {
|
||||
handler.send_mouse((evt.buttons << 3) | 1, x + display_origin_x, y + display_origin_y, evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey);
|
||||
}
|
||||
last_mouse_mask = mask;
|
||||
// to-do: altKey, ctrlKey etc
|
||||
handler.send_mouse((evt.buttons << 3) | mask,
|
||||
mask == 3 ? wheel_delta_x : x + display_origin_x,
|
||||
mask == 3 ? wheel_delta_y : y + display_origin_y,
|
||||
evt.altKey,
|
||||
evt.ctrlKey, evt.shiftKey, evt.commandKey);
|
||||
return true;
|
||||
};
|
||||
// // TODO
|
||||
// handler.onMouse(evt)
|
||||
// {
|
||||
// if (is_file_transfer || is_port_forward) return false;
|
||||
// if (view.windowState == View.WINDOW_FULL_SCREEN && !dragging) {
|
||||
// var dy = evt.y - scroll_body.scroll(#top);
|
||||
// if (dy <= 1) {
|
||||
// if (!wait_window_toolbar) {
|
||||
// wait_window_toolbar = true;
|
||||
// self.timer(300ms, function() {
|
||||
// if (!wait_window_toolbar) return;
|
||||
// var extra = 0;
|
||||
// // workaround for stupid Sciter, without this, click
|
||||
// // event not triggered on top part of buttons on toolbar
|
||||
// if (is_osx) extra = 10;
|
||||
// if (view.windowState == View.WINDOW_FULL_SCREEN) {
|
||||
// $(header).style.set {
|
||||
// display: "block",
|
||||
// padding: (2 * workarea_offset + extra) + "px 0 0 0",
|
||||
// };
|
||||
// }
|
||||
// wait_window_toolbar = false;
|
||||
// });
|
||||
// }
|
||||
// } else {
|
||||
// wait_window_toolbar = false;
|
||||
// var h = $(header).style;
|
||||
// if (dy > 20 && h#display != "none") {
|
||||
// h.set {
|
||||
// display: "none",
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (!got_mouse_control) {
|
||||
// if (Math.abs(evt.x - cur_local_x) > 12 || Math.abs(evt.y - cur_local_y) > 12) {
|
||||
// got_mouse_control = true;
|
||||
// } else {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// var mask = 0;
|
||||
// var wheel_delta_x;
|
||||
// var wheel_delta_y;
|
||||
// switch(evt.type) {
|
||||
// case Event.MOUSE_DOWN:
|
||||
// mask = 1;
|
||||
// dragging = true;
|
||||
// break;
|
||||
// case Event.MOUSE_UP:
|
||||
// mask = 2;
|
||||
// dragging = false;
|
||||
// break;
|
||||
// case Event.MOUSE_MOVE:
|
||||
// if (cursor_img.style#display != "none" && keyboard_enabled) {
|
||||
// cursor_img.style#display = "none";
|
||||
// handler.style#cursor = '';
|
||||
// }
|
||||
// break;
|
||||
// case Event.MOUSE_WHEEL:
|
||||
// // mouseWheelDistance = 8 * [currentUserDefs floatForKey:@"com.apple.scrollwheel.scaling"];
|
||||
// mask = 3;
|
||||
// {
|
||||
// var (dx, dy) = evt.wheelDeltas;
|
||||
// if (dx > 0) dx = 1;
|
||||
// else if (dx < 0) dx = -1;
|
||||
// if (dy > 0) dy = 1;
|
||||
// else if (dy < 0) dy = -1;
|
||||
// if (Math.abs(dx) > Math.abs(dy)) {
|
||||
// dy = 0;
|
||||
// } else {
|
||||
// dx = 0;
|
||||
// }
|
||||
// acc_wheel_delta_x += dx;
|
||||
// acc_wheel_delta_y += dy;
|
||||
// wheel_delta_x = acc_wheel_delta_x.toInteger();
|
||||
// wheel_delta_y = acc_wheel_delta_y.toInteger();
|
||||
// acc_wheel_delta_x -= wheel_delta_x;
|
||||
// acc_wheel_delta_y -= wheel_delta_y;
|
||||
// var now = getTime();
|
||||
// var dt = last_wheel_time > 0 ? (now - last_wheel_time) / 1000 : 0;
|
||||
// if (dt > 0) {
|
||||
// var vx = dx / dt;
|
||||
// var vy = dy / dt;
|
||||
// if (vx != 0 || vy != 0) {
|
||||
// inertia_velocity_x = vx;
|
||||
// inertia_velocity_y = vy;
|
||||
// }
|
||||
// }
|
||||
// acc_wheel_delta_x0 += dx;
|
||||
// acc_wheel_delta_y0 += dy;
|
||||
// total_wheel_time += dt;
|
||||
// if (dx == 0 && dy == 0) {
|
||||
// wheeling = false;
|
||||
// if (dt < 0.1 && total_wheel_time > 0) {
|
||||
// var v2 = (acc_wheel_delta_y0 / total_wheel_time) * inertia_velocity_y;
|
||||
// if (v2 > 0) {
|
||||
// v2 = Math.sqrt(v2);
|
||||
// inertia_velocity_y = inertia_velocity_y < 0 ? -v2 : v2;
|
||||
// accWheel(inertia_velocity_y, false);
|
||||
// }
|
||||
// v2 = (acc_wheel_delta_x0 / total_wheel_time) * inertia_velocity_x;
|
||||
// if (v2 > 0) {
|
||||
// v2 = Math.sqrt(v2);
|
||||
// inertia_velocity_x = inertia_velocity_x < 0 ? -v2 : v2;
|
||||
// accWheel(inertia_velocity_x, true);
|
||||
// }
|
||||
// }
|
||||
// resetWheel();
|
||||
// } else {
|
||||
// wheeling = true;
|
||||
// }
|
||||
// last_wheel_time = now;
|
||||
// if (wheel_delta_x == 0 && wheel_delta_y == 0) return keyboard_enabled;
|
||||
// }
|
||||
// break;
|
||||
// case Event.MOUSE_DCLICK: // seq: down, up, dclick, up
|
||||
// mask = 1;
|
||||
// break;
|
||||
// case Event.MOUSE_ENTER:
|
||||
// entered = true;
|
||||
// console.log("enter");
|
||||
// return keyboard_enabled;
|
||||
// case Event.MOUSE_LEAVE:
|
||||
// entered = false;
|
||||
// console.log("leave");
|
||||
// return keyboard_enabled;
|
||||
// default:
|
||||
// return false;
|
||||
// }
|
||||
// var x = evt.x;
|
||||
// var y = evt.y;
|
||||
// if (mask != 0) {
|
||||
// // to gain control of the mouse, user must move mouse
|
||||
// if (cur_x != x || cur_y != y) {
|
||||
// return keyboard_enabled;
|
||||
// }
|
||||
// // save bandwidth
|
||||
// x = 0;
|
||||
// y = 0;
|
||||
// } else {
|
||||
// cur_local_x = cur_x = x;
|
||||
// cur_local_y = cur_y = y;
|
||||
// }
|
||||
// if (mask != 3) {
|
||||
// resetWheel();
|
||||
// }
|
||||
// if (!keyboard_enabled) return false;
|
||||
// x = (x / display_scale).toInteger();
|
||||
// y = (y / display_scale).toInteger();
|
||||
// // insert down between two up, osx has this behavior for triple click
|
||||
// if (last_mouse_mask == 2 && mask == 2) {
|
||||
// handler.send_mouse((evt.buttons << 3) | 1, x + display_origin_x, y + display_origin_y, evt.altKey,
|
||||
// evt.ctrlKey, evt.shiftKey, evt.commandKey);
|
||||
// }
|
||||
// last_mouse_mask = mask;
|
||||
// // to-do: altKey, ctrlKey etc
|
||||
// handler.send_mouse((evt.buttons << 3) | mask,
|
||||
// mask == 3 ? wheel_delta_x : x + display_origin_x,
|
||||
// mask == 3 ? wheel_delta_y : y + display_origin_y,
|
||||
// evt.altKey,
|
||||
// evt.ctrlKey, evt.shiftKey, evt.commandKey);
|
||||
// return true;
|
||||
// };
|
||||
|
||||
var cur_hotx = 0;
|
||||
var cur_hoty = 0;
|
||||
@ -340,36 +348,33 @@ var image_binded;
|
||||
handler.setCursorData = function(id, hotx, hoty, width, height, colors) {
|
||||
cur_hotx = hotx;
|
||||
cur_hoty = hoty;
|
||||
cursor_img.style.set {
|
||||
width: width + "px",
|
||||
height: height + "px",
|
||||
};
|
||||
var img = Image.fromBytes(colors);
|
||||
cursor_img.style.setProperty("width",width + "px");
|
||||
cursor_img.style.setProperty("height",height + "px");
|
||||
|
||||
let img = Image.fromBytes(colors);
|
||||
if (img) {
|
||||
image_binded = true;
|
||||
cursors[id] = [img, hotx, hoty, width, height];
|
||||
this.bindImage("in-memory:cursor", img);
|
||||
if (cursor_img.style#display == 'none') {
|
||||
self.timer(1ms, function() { handler.style.cursor(cur_img, cur_hotx, cur_hoty); });
|
||||
if (cursor_img.style.getProperty("display") == 'none') { // TEST getProperty
|
||||
setTimeout(function() { handler.style.cursor(cur_img, cur_hotx, cur_hoty) },1); // TODO cursor
|
||||
}
|
||||
cur_img = img;
|
||||
}
|
||||
}
|
||||
|
||||
handler.setCursorId = function(id) {
|
||||
var img = cursors[id];
|
||||
let img = cursors[id];
|
||||
if (img) {
|
||||
image_binded = true;
|
||||
cur_hotx = img[1];
|
||||
cur_hoty = img[2];
|
||||
cursor_img.style.set {
|
||||
width: img[3] + "px",
|
||||
height: img[4] + "px",
|
||||
};
|
||||
cursor_img.style.setProperty("width",img[3] + "px");
|
||||
cursor_img.style.setProperty("height",img[4] + "px");
|
||||
img = img[0];
|
||||
this.bindImage("in-memory:cursor", img);
|
||||
if (cursor_img.style#display == 'none') {
|
||||
self.timer(1ms, function() { handler.style.cursor(cur_img, cur_hotx, cur_hoty); });
|
||||
if (cursor_img.style.getProperty("display") == 'none') {
|
||||
setTimeout(function() { handler.style.cursor(cur_img, cur_hotx, cur_hoty) },1);
|
||||
}
|
||||
cur_img = img;
|
||||
}
|
||||
@ -385,21 +390,19 @@ handler.setCursorPosition = function(x, y) {
|
||||
var y = cur_y - cur_hoty;
|
||||
x *= display_scale;
|
||||
y *= display_scale;
|
||||
cursor_img.style.set {
|
||||
left: x + "px",
|
||||
top: y + "px",
|
||||
};
|
||||
if (cursor_img.style#display == 'none') {
|
||||
handler.style#cursor = 'none';
|
||||
cursor_img.style#display = "block";
|
||||
cursor_img.style.setProperty("width",x + "px");
|
||||
cursor_img.style.setProperty("width",y + "px");
|
||||
if (cursor_img.style.getProperty("display") == 'none') {
|
||||
handler.style.setProperty("cursor",'none');
|
||||
cursor_img.style.setProperty("display","block");
|
||||
}
|
||||
}
|
||||
|
||||
function self.ready() {
|
||||
var w = 960;
|
||||
var h = 640;
|
||||
document.on("ready",()=> {
|
||||
let w = 960;
|
||||
let h = 640;
|
||||
if (is_file_transfer || is_port_forward) {
|
||||
var r = handler.get_size();
|
||||
let r = handler.xcall("get_size");
|
||||
if (isReasonableSize(r) && r[2] > 0) {
|
||||
view.move(r[0], r[1], r[2], r[3]);
|
||||
} else {
|
||||
@ -411,53 +414,54 @@ function self.ready() {
|
||||
if (!is_port_forward) connecting();
|
||||
if (is_file_transfer) initializeFileTransfer();
|
||||
if (is_port_forward) initializePortForward();
|
||||
}
|
||||
})
|
||||
|
||||
var workarea_offset = 0;
|
||||
var size_adapted;
|
||||
handler.adaptSize = function() {
|
||||
if (size_adapted) return;
|
||||
size_adapted = true;
|
||||
var (sx, sy, sw, sh) = view.screenBox(#workarea, #rectw);
|
||||
var (fx, fy, fw, fh) = view.screenBox(#frame, #rectw);
|
||||
let [sx, sy, sw, sh] = view.screenBox("workarea", "rectw");
|
||||
let [fx, fy, fw, fh] = view.screenBox("frame", "rectw");
|
||||
if (is_osx) workarea_offset = sy;
|
||||
var r = handler.get_size();
|
||||
let r = handler.xcall("get_size");
|
||||
if (isReasonableSize(r) && r[2] > 0) {
|
||||
if (r[2] >= fw && r[3] >= fh && !is_linux) {
|
||||
view.windowState = View.WINDOW_FULL_SCREEN;
|
||||
stdout.println("Initialize to full screen");
|
||||
view.state = Window.WINDOW_FULL_SCREEN;
|
||||
console.log("Initialize to full screen");
|
||||
} else if (r[2] >= sw && r[3] >= sh) {
|
||||
view.windowState = View.WINDOW_MAXIMIZED;
|
||||
stdout.println("Initialize to full screen");
|
||||
view.state = Window.WINDOW_MAXIMIZED;
|
||||
console.log("Initialize to full screen");
|
||||
} else {
|
||||
view.move(r[0], r[1], r[2], r[3]);
|
||||
}
|
||||
} else {
|
||||
var w = handler.box(#width, #border)
|
||||
var h = handler.box(#height, #border)
|
||||
let w = handler.state.box("width", "border")
|
||||
let h = handler.state.box("height", "border")
|
||||
if (w >= sw || h >= sh) {
|
||||
view.windowState = View.WINDOW_MAXIMIZED;
|
||||
view.state = Window.WINDOW_MAXIMIZED;
|
||||
return;
|
||||
}
|
||||
// extra for border
|
||||
var extra = 2;
|
||||
centerize(w + extra, handler.box(#height, #border) + h + extra);
|
||||
let extra = 2;
|
||||
centerize(w + extra, handler.state.box("height", "border") + h + extra);
|
||||
}
|
||||
}
|
||||
|
||||
function self.closing() {
|
||||
var (x, y, w, h) = view.box(#rectw, #border, #screen);
|
||||
document.on("unloadequest",()=> {
|
||||
let [x, y, w, h] = view.state.box("rectw", "border", "screen");
|
||||
if (is_file_transfer) save_file_transfer_close_state();
|
||||
if (is_file_transfer || is_port_forward || size_adapted) handler.save_size(x, y, w, h);
|
||||
}
|
||||
if (is_file_transfer || is_port_forward || size_adapted) handler.xcall("save_size",x, y, w, h);
|
||||
})
|
||||
|
||||
handler.setPermission = function(name, enabled) {
|
||||
if (name == "keyboard") keyboard_enabled = enabled;
|
||||
if (name == "audio") audio_enabled = enabled;
|
||||
if (name == "clipboard") clipboard_enabled = enabled;
|
||||
header.update();
|
||||
header.componentUpdate();
|
||||
}
|
||||
|
||||
// TODO
|
||||
handler.closeSuccess = function() {
|
||||
// handler.msgbox("success", "Successful", "Ready to go.");
|
||||
handler.msgbox("", "", "");
|
||||
|
@ -75,7 +75,7 @@ impl Deref for Handler {
|
||||
|
||||
impl sciter::EventHandler for Handler {
|
||||
fn get_subscription(&mut self) -> Option<EVENT_GROUPS> {
|
||||
Some(EVENT_GROUPS::HANDLE_BEHAVIOR_EVENT)
|
||||
Some(EVENT_GROUPS::HANDLE_METHOD_CALL | EVENT_GROUPS::HANDLE_SCRIPTING_METHOD_CALL | EVENT_GROUPS::HANDLE_BEHAVIOR_EVENT)
|
||||
}
|
||||
|
||||
fn attached(&mut self, root: HELEMENT) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user