From f3a8f17ef127b9c62a3ecb2d11f9b7ddc84ec85d Mon Sep 17 00:00:00 2001 From: DanyLE Date: Wed, 17 Aug 2022 18:43:52 +0200 Subject: [PATCH] RemoteDesktop: sync clipboard between local and remote --- RemoteDesktop/README.md | 1 + RemoteDesktop/build/debug/README.md | 1 + RemoteDesktop/build/debug/main.js | 2 +- RemoteDesktop/build/debug/package.json | 2 +- RemoteDesktop/build/release/RemoteDesktop.zip | Bin 71322 -> 71538 bytes RemoteDesktop/coffees/WVNC.coffee | 7 +++++- RemoteDesktop/coffees/main.coffee | 23 +++++++++++++++++- RemoteDesktop/package.json | 2 +- packages.json | 2 +- 9 files changed, 34 insertions(+), 6 deletions(-) diff --git a/RemoteDesktop/README.md b/RemoteDesktop/README.md index 094f548..a5ffe16 100644 --- a/RemoteDesktop/README.md +++ b/RemoteDesktop/README.md @@ -7,6 +7,7 @@ Further information on **wvnc**: [https://blog.lxsang.me/post/id/23](https://blo ## Change logs +* v0.1.10 - Allow to sync clipboard between local and remote machine, CTRL+SHIF+V to paste text from local to remote machine * v0.1.9 - improve stability * v0.1.7-8 - remove package dependencies, use web assembly for jpeg decoding, improve rendering performance and connection stability * v0.1.6 - Change category diff --git a/RemoteDesktop/build/debug/README.md b/RemoteDesktop/build/debug/README.md index 094f548..a5ffe16 100644 --- a/RemoteDesktop/build/debug/README.md +++ b/RemoteDesktop/build/debug/README.md @@ -7,6 +7,7 @@ Further information on **wvnc**: [https://blog.lxsang.me/post/id/23](https://blo ## Change logs +* v0.1.10 - Allow to sync clipboard between local and remote machine, CTRL+SHIF+V to paste text from local to remote machine * v0.1.9 - improve stability * v0.1.7-8 - remove package dependencies, use web assembly for jpeg decoding, improve rendering performance and connection stability * v0.1.6 - Change category diff --git a/RemoteDesktop/build/debug/main.js b/RemoteDesktop/build/debug/main.js index 447a753..70aa84d 100644 --- a/RemoteDesktop/build/debug/main.js +++ b/RemoteDesktop/build/debug/main.js @@ -1 +1 @@ -(function(){var e,t,n,s;(e=class e extends this.OS.GUI.BasicDialog{constructor(){super("ConnectionDialog",e.scheme)}main(){return super.main(),this.find("jq").value=40,this.find("bt-ok").onbtclick=e=>{var t;if(this.handle)return t={wvnc:this.find("txtWVNC").value,server:this.find("txtServer").value,quality:this.find("jq").value},this.handle(t),this.quit()},this.find("bt-cancel").onbtclick=e=>this.quit()}}).scheme='\n \n
\n \n \n \n \n \n
\n \n \n \n
\n \n \n
\n
\n
\n
\n
\n
\n
\n',(t=class e extends this.OS.GUI.BasicDialog{constructor(){super("CredentialDialog",e.scheme)}main(){return this.find("bt-ok").onbtclick=()=>{var e;return this.handle?(e={username:this.find("txtUser").value,password:this.find("txtPass").value},this.handle(e),this.quit()):this.quit()},this.find("bt-cancel").onbtclick=()=>this.quit()}}).scheme='\n \n \n \n \n \n \n
\n \n \n
\n
\n
\n
\n
',n=class extends this.OS.application.BaseApplication{constructor(e){super("RemoteDesktop",e)}main(){return this.canvas=this.find("screen"),this.container=this.find("container"),this.client=new s({element:this.canvas}),this.client.onerror=e=>(this.error(e),this.showConnectionDialog()),this.client.onresize=()=>this.setScale(),this.client.onpassword=()=>new Promise((e,t)=>this.openDialog("PromptDialog",{title:__("VNC password"),label:__("VNC password"),value:"password",type:"password"}).then((function(t){return e(t)}))),this.client.oncredential=()=>new Promise((e,n)=>this.openDialog(new t,{title:__("User credential")}).then((function(t){return e(t.username,t.password)}))),this.on("resize",e=>this.setScale()),this.on("focus",e=>$(this.canvas).focus()),this.client.init().then(()=>this.showConnectionDialog())}setScale(){var e,t,n,s;if(this.client&&this.client.resolution)return s=$(this.container).width(),e=$(this.container).height(),(t=s/this.client.resolution.w)>(n=e/this.client.resolution.h)?this.client.setScale(n):this.client.setScale(t)}menu(){return[{text:"__(Connection)",nodes:[{text:"__(New Connection)",dataid:this.name+"-new"},{text:"__(Disconnect)",dataid:this.name+"-close"}],onchildselect:e=>this.actionConnection()}]}actionConnection(e){return this.client&&this.client.disconnect(!1),this.showConnectionDialog()}showConnectionDialog(){return this.openDialog(new e,{title:__("Connection")}).then(e=>(this.client.ws=e.wvnc,this.client.connect(e.server,e)))}cleanup(){if(this.client)return this.client.disconnect(!0)}},this.OS.register("RemoteDesktop",n),s=class{constructor(e){var t,n;this.socket=void 0,this.ws=void 0,this.canvas=void 0,n="pkg://RemoteDesktop/decoder_asm.js".asFileHandle().getlink(),this.scale=1,e.ws&&(this.ws=e.ws),this.canvas=e.element,"string"==typeof this.canvas&&(this.canvas=document.getElementById(this.canvas)),this.decoder=new Worker(n),this.enableEvent=!1,this.pingto=!1,t=this,this.mouseMask=0,this.decoder.onmessage=function(e){return t.process(e.data)}}init(){var e;return e=this,new Promise((function(t,n){return e.canvas?($(e.canvas).attr("tabindex","1"),$(e.canvas).on("focus",()=>e.resetModifierKeys()),e.initInputEvent(),t()):n("Canvas is not set")}))}initInputEvent(){var e,t,n,s;if(n=this,this.canvas&&(t=function(e){var t;return t=n.canvas.getBoundingClientRect(),{x:Math.floor((e.clientX-t.left)/n.scale),y:Math.floor((e.clientY-t.top)/n.scale)}},s=function(e){var s;if(n.enableEvent)return s=t(e),n.sendPointEvent(s.x,s.y,n.mouseMask)},n.canvas))return n.canvas.oncontextmenu=function(e){return e.preventDefault(),!1},n.canvas.onmousemove=function(e){return s(e)},n.canvas.onmousedown=function(e){var t;return t=1<this.disconnect(!0),window.addEventListener("unload",e),window.addEventListener("beforeunload",e)}initCanvas(e,t,n){return this.depth=n,this.canvas.width=e,this.canvas.height=t,this.resolution={w:e,h:t,depth:this.depth},this.decoder.postMessage(this.resolution),this.setScale(this.scale)}process(e){var t,n,s;if(this.socket)return n=new Uint8Array(e.pixels),(s=(t=this.canvas.getContext("2d",{alpha:!1})).createImageData(e.w,e.h)).data.set(n),t.putImageData(s,e.x,e.y)}setScale(e){if(this.scale=e,this.canvas)return this.canvas.style.transformOrigin="0 0",this.canvas.style.transform="scale("+e+")"}connect(e,t){var n;if(n=this,this.disconnect(!1),this.ws)return this.socket=new WebSocket(this.ws),this.socket.binaryType="arraybuffer",this.socket.onopen=function(){return console.log("socket opened"),n.initConnection(e,t)},this.socket.onmessage=function(e){return n.consume(e)},this.socket.onclose=function(){return n.socket=null,n.canvas.style.cursor="auto",n.canvas&&n.resolution&&n.canvas.getContext("2d").clearRect(0,0,n.resolution.w,n.resolution.h),n.pingto&&clearTimeout(n.pingto),n.pingto=void 0,console.log("socket closed")}}disconnect(e){return this.socket&&this.socket.close(),this.socket=void 0,e&&this.decoder.terminate(),this.enableEvent=!1}initConnection(e,t){var n;return(n=new Uint8Array(e.length+1))[0]=50,t&&t.quality&&(n[0]=t.quality),n.set((new TextEncoder).encode(e),1),this.socket.send(this.buildCommand(1,n))}resetModifierKeys(){if(this.socket&&this.enableEvent)return this.sendKeyEvent(65511,0),this.sendKeyEvent(65512,0),this.sendKeyEvent(65505,0),this.sendKeyEvent(65507,0),this.sendKeyEvent(65513,0)}sendPointEvent(e,t,n){var s;if(this.socket&&this.enableEvent)return(s=new Uint8Array(5))[0]=255&e,s[1]=e>>8,s[2]=255&t,s[3]=t>>8,s[4]=n,this.socket.send(this.buildCommand(5,s))}sendKeyEvent(e,t){var n;if(this.socket&&this.enableEvent)return(n=new Uint8Array(3))[0]=255&e,n[1]=e>>8&255,n[2]=t,this.socket.send(this.buildCommand(6,n))}sendPing(){if(this.socket)return this.socket.send(this.buildCommand(8,"PING WVNC"))}buildCommand(e,t){var n,s;switch(s=void 0,typeof t){case"string":s=(new TextEncoder).encode(t);break;case"number":s=new Uint8Array([t]);break;default:s=t}return(n=new Uint8Array(s.length+3))[0]=e,n[2]=s.length>>8,n[1]=15&s.length,n.set(s,3),n.buffer}oncopy(e){return console.log("Get clipboard text: "+e)}onpassword(){return new Promise((function(e,t){return t("onpassword is not implemented")}))}sendTextAsClipboard(e){if(this.socket)return console.log("send ",e),this.socket.send(this.buildCommand(7,e))}oncredential(){return new Promise((function(e,t){return t("oncredential is not implemented")}))}onerror(e){return console.log("Error",e)}onresize(){return console.log("resize")}consume(e){var t,n,s,i,a,o,r;switch(t=(n=new Uint8Array(e.data))[0],o=this,t){case 254:return n=n.subarray(1,n.length-1),s=new TextDecoder("utf-8"),this.onerror(s.decode(n));case 129:return console.log("Request for password"),this.enableEvent=!1,this.onpassword().then((function(e){return o.socket.send(o.buildCommand(2,e)),o.enableEvent=!0}));case 130:return console.log("Request for login"),this.enableEvent=!1,this.oncredential().then((function(e,t){var n;return(n=new Uint8Array(e.length+t.length+1)).set((new TextEncoder).encode(e),0),n.set(["\0"],e.length),n.set((new TextEncoder).encode(t),e.length+1),o.socket.send(o.buildCommand(3,n)),o.enableEvent=!0}));case 131:if(r=n[1]|n[2]<<8,a=n[3]|n[4]<<8,this.initCanvas(r,a,32),this.socket.send(this.buildCommand(4,1)),this.enableEvent=!0,this.onresize(),this.pingto)return;return i=()=>(this.sendPing(),this.pingto=setTimeout(i,5e3)),this.pingto=setTimeout(i,5e3);case 132:return this.decoder.postMessage(n.buffer,[n.buffer]),this.socket.send(this.buildCommand(4,1));case 133:return n=n.subarray(1),s=new TextDecoder("utf-8"),this.oncopy(s.decode(n)),this.socket.send(this.buildCommand(4,1));default:return console.log(t)}}},window.WVNC=s}).call(this); \ No newline at end of file +(function(){var e,t,n,s;(e=class e extends this.OS.GUI.BasicDialog{constructor(){super("ConnectionDialog",e.scheme)}main(){return super.main(),this.find("jq").value=40,this.find("bt-ok").onbtclick=e=>{var t;if(this.handle)return t={wvnc:this.find("txtWVNC").value,server:this.find("txtServer").value,quality:this.find("jq").value},this.handle(t),this.quit()},this.find("bt-cancel").onbtclick=e=>this.quit()}}).scheme='\n \n
\n \n \n \n \n \n
\n \n \n \n
\n \n \n
\n
\n
\n
\n
\n
\n
\n',(t=class e extends this.OS.GUI.BasicDialog{constructor(){super("CredentialDialog",e.scheme)}main(){return this.find("bt-ok").onbtclick=()=>{var e;return this.handle?(e={username:this.find("txtUser").value,password:this.find("txtPass").value},this.handle(e),this.quit()):this.quit()},this.find("bt-cancel").onbtclick=()=>this.quit()}}).scheme='\n \n \n \n \n \n \n
\n \n \n
\n
\n
\n
\n
',n=class extends this.OS.application.BaseApplication{constructor(e){super("RemoteDesktop",e)}main(){return this.canvas=this.find("screen"),this.container=this.find("container"),this.client=new s({element:this.canvas}),this.bindKey("CTRL-SHIFT-V",e=>this.pasteText()),this.client.onerror=e=>(this.error(e),this.showConnectionDialog()),this.client.onresize=()=>this.setScale(),this.client.onpassword=()=>new Promise((e,t)=>this.openDialog("PromptDialog",{title:__("VNC password"),label:__("VNC password"),value:"password",type:"password"}).then((function(t){return e(t)}))),this.client.oncopy=e=>this._api.setClipboard(e),this.client.oncredential=()=>new Promise((e,n)=>this.openDialog(new t,{title:__("User credential")}).then((function(t){return e(t.username,t.password)}))),this.on("resize",e=>this.setScale()),this.on("focus",e=>$(this.canvas).focus()),this.client.init().then(()=>this.showConnectionDialog())}pasteText(){var e;if(this.client)return e=e=>{if(e&&""!==e)return this.client.sendTextAsClipboard(e)},this._api.getClipboard().then(t=>e(t)).catch(t=>(this.error(__("Unable to paste"),t),this.openDialog("TextDialog",{title:"Paste text"}).then(t=>e(t)).catch(e=>this.error(e.toString(),e))))}setScale(){var e,t,n,s;if(this.client&&this.client.resolution)return s=$(this.container).width(),e=$(this.container).height(),(t=s/this.client.resolution.w)>(n=e/this.client.resolution.h)?this.client.setScale(n):this.client.setScale(t)}menu(){return[{text:"__(Connection)",nodes:[{text:"__(New Connection)",dataid:this.name+"-new"},{text:"__(Disconnect)",dataid:this.name+"-close"}],onchildselect:e=>this.actionConnection()}]}actionConnection(e){return this.client&&this.client.disconnect(!1),this.showConnectionDialog()}showConnectionDialog(){return this.openDialog(new e,{title:__("Connection")}).then(e=>(this.client.ws=e.wvnc,this.client.connect(e.server,e)))}cleanup(){if(this.client)return this.client.disconnect(!0)}},this.OS.register("RemoteDesktop",n),s=class{constructor(e){var t,n;this.socket=void 0,this.ws=void 0,this.canvas=void 0,n="pkg://RemoteDesktop/decoder_asm.js".asFileHandle().getlink(),this.scale=1,e.ws&&(this.ws=e.ws),this.canvas=e.element,"string"==typeof this.canvas&&(this.canvas=document.getElementById(this.canvas)),this.decoder=new Worker(n),this.enableEvent=!1,this.pingto=!1,t=this,this.mouseMask=0,this.decoder.onmessage=function(e){return t.process(e.data)}}init(){var e;return e=this,new Promise((function(t,n){return e.canvas?($(e.canvas).attr("tabindex","1"),$(e.canvas).on("focus",()=>e.resetModifierKeys()),e.initInputEvent(),t()):n("Canvas is not set")}))}initInputEvent(){var e,t,n,s;if(n=this,this.canvas&&(t=function(e){var t;return t=n.canvas.getBoundingClientRect(),{x:Math.floor((e.clientX-t.left)/n.scale),y:Math.floor((e.clientY-t.top)/n.scale)}},s=function(e){var s;if(n.enableEvent)return s=t(e),n.sendPointEvent(s.x,s.y,n.mouseMask)},n.canvas))return n.canvas.oncontextmenu=function(e){return e.preventDefault(),!1},n.canvas.onmousemove=function(e){return s(e)},n.canvas.onmousedown=function(e){var t;return t=1<this.disconnect(!0),window.addEventListener("unload",e),window.addEventListener("beforeunload",e)}initCanvas(e,t,n){return this.depth=n,this.canvas.width=e,this.canvas.height=t,this.resolution={w:e,h:t,depth:this.depth},this.decoder.postMessage(this.resolution),this.setScale(this.scale)}process(e){var t,n,s;if(this.socket)return n=new Uint8Array(e.pixels),(s=(t=this.canvas.getContext("2d",{alpha:!1})).createImageData(e.w,e.h)).data.set(n),t.putImageData(s,e.x,e.y)}setScale(e){if(this.scale=e,this.canvas)return this.canvas.style.transformOrigin="0 0",this.canvas.style.transform="scale("+e+")"}connect(e,t){var n;if(n=this,this.disconnect(!1),this.ws)return this.socket=new WebSocket(this.ws),this.socket.binaryType="arraybuffer",this.socket.onopen=function(){return console.log("socket opened"),n.initConnection(e,t)},this.socket.onmessage=function(e){return n.consume(e)},this.socket.onclose=function(){return n.socket=null,n.canvas.style.cursor="auto",n.canvas&&n.resolution&&n.canvas.getContext("2d").clearRect(0,0,n.resolution.w,n.resolution.h),n.pingto&&clearTimeout(n.pingto),n.pingto=void 0,console.log("socket closed")}}disconnect(e){return this.socket&&this.socket.close(),this.socket=void 0,e&&this.decoder.terminate(),this.enableEvent=!1}initConnection(e,t){var n;return(n=new Uint8Array(e.length+1))[0]=50,t&&t.quality&&(n[0]=t.quality),n.set((new TextEncoder).encode(e),1),this.socket.send(this.buildCommand(1,n))}resetModifierKeys(){if(this.socket&&this.enableEvent)return this.sendKeyEvent(65511,0),this.sendKeyEvent(65512,0),this.sendKeyEvent(65505,0),this.sendKeyEvent(65507,0),this.sendKeyEvent(65513,0)}sendPointEvent(e,t,n){var s;if(this.socket&&this.enableEvent)return(s=new Uint8Array(5))[0]=255&e,s[1]=e>>8,s[2]=255&t,s[3]=t>>8,s[4]=n,this.socket.send(this.buildCommand(5,s))}sendKeyEvent(e,t){var n;if(this.socket&&this.enableEvent)return(n=new Uint8Array(3))[0]=255&e,n[1]=e>>8&255,n[2]=t,this.socket.send(this.buildCommand(6,n))}sendPing(){if(this.socket)return this.socket.send(this.buildCommand(8,"PING WVNC"))}buildCommand(e,t){var n,s;switch(s=void 0,typeof t){case"string":s=(new TextEncoder).encode(t);break;case"number":s=new Uint8Array([t]);break;default:s=t}return(n=new Uint8Array(s.length+3))[0]=e,n[2]=s.length>>8,n[1]=15&s.length,n.set(s,3),n.buffer}oncopy(e){return console.log("Get clipboard text: "+e)}onpassword(){return new Promise((function(e,t){return t("onpassword is not implemented")}))}sendTextAsClipboard(e){var t;if(this.socket)return this.socket.send(this.buildCommand(7,e)),t="v".charCodeAt(0),this.sendKeyEvent(65507,1),this.sendKeyEvent(t,1),this.sendKeyEvent(t,0),this.sendKeyEvent(65507,0)}oncredential(){return new Promise((function(e,t){return t("oncredential is not implemented")}))}onerror(e){return console.log("Error",e)}onresize(){return console.log("resize")}consume(e){var t,n,s,i,a,o,r;switch(t=(n=new Uint8Array(e.data))[0],o=this,t){case 254:return n=n.subarray(1,n.length-1),s=new TextDecoder("utf-8"),this.onerror(s.decode(n));case 129:return console.log("Request for password"),this.enableEvent=!1,this.onpassword().then((function(e){return o.socket.send(o.buildCommand(2,e)),o.enableEvent=!0}));case 130:return console.log("Request for login"),this.enableEvent=!1,this.oncredential().then((function(e,t){var n;return(n=new Uint8Array(e.length+t.length+1)).set((new TextEncoder).encode(e),0),n.set(["\0"],e.length),n.set((new TextEncoder).encode(t),e.length+1),o.socket.send(o.buildCommand(3,n)),o.enableEvent=!0}));case 131:if(r=n[1]|n[2]<<8,a=n[3]|n[4]<<8,this.initCanvas(r,a,32),this.socket.send(this.buildCommand(4,1)),this.enableEvent=!0,this.onresize(),this.pingto)return;return i=()=>(this.sendPing(),this.pingto=setTimeout(i,5e3)),this.pingto=setTimeout(i,5e3);case 132:return this.decoder.postMessage(n.buffer,[n.buffer]),this.socket.send(this.buildCommand(4,1));case 133:return n=n.subarray(1),s=new TextDecoder("utf-8"),this.oncopy(s.decode(n)),this.socket.send(this.buildCommand(4,1));default:return console.log(t)}}},window.WVNC=s}).call(this); \ No newline at end of file diff --git a/RemoteDesktop/build/debug/package.json b/RemoteDesktop/build/debug/package.json index b2987bd..5281648 100644 --- a/RemoteDesktop/build/debug/package.json +++ b/RemoteDesktop/build/debug/package.json @@ -7,7 +7,7 @@ "author": "Dany LE", "email": "contact@iohub.dev" }, - "version":"0.1.9-b", + "version":"0.1.10-b", "dependencies": [], "category":"Internet", "icon": "icon.png", diff --git a/RemoteDesktop/build/release/RemoteDesktop.zip b/RemoteDesktop/build/release/RemoteDesktop.zip index 45036fff8c1fa7d6adeec0987395b7a057b87664..8227134769479320810e467437764b66ef79a737 100644 GIT binary patch delta 4658 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 PZh%>eo@SzdVh delta 4380 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 UBfRmafcUzfU4N4(n(GPlFMX^J=Kufz diff --git a/RemoteDesktop/coffees/WVNC.coffee b/RemoteDesktop/coffees/WVNC.coffee index 6a8741e..00a312b 100644 --- a/RemoteDesktop/coffees/WVNC.coffee +++ b/RemoteDesktop/coffees/WVNC.coffee @@ -262,8 +262,13 @@ class WVNC sendTextAsClipboard: (text) -> return unless @socket - console.log "send ", text @socket.send (@buildCommand 0x07, text) + # send ctrl-v to paste + charcode = 'v'.charCodeAt 0 + @sendKeyEvent 0xFFE3, 1 # CTRL down + @sendKeyEvent charcode, 1 # v down + @sendKeyEvent charcode, 0 # v up + @sendKeyEvent 0xFFE3, 0 # CTRL up oncredential: () -> return new Promise (resolve, reject) -> diff --git a/RemoteDesktop/coffees/main.coffee b/RemoteDesktop/coffees/main.coffee index b7dbc4d..8526dfa 100644 --- a/RemoteDesktop/coffees/main.coffee +++ b/RemoteDesktop/coffees/main.coffee @@ -88,6 +88,8 @@ class RemoteDesktop extends this.OS.application.BaseApplication @client = new WVNC { element: @canvas } + @bindKey "CTRL-SHIFT-V", (e) => + @pasteText() @client.onerror = (m) => @error m @showConnectionDialog() @@ -103,7 +105,9 @@ class RemoteDesktop extends this.OS.application.BaseApplication } .then (d) -> r(d) - + @client.oncopy = (text) => + @_api.setClipboard text + @client.oncredential = () => return new Promise (r,e) => @openDialog new CredentialDialog, { title: __("User credential") } @@ -114,6 +118,23 @@ class RemoteDesktop extends this.OS.application.BaseApplication @client.init().then () => @showConnectionDialog() + pasteText: () -> + return unless @client + cb = (text) => + return unless text and text isnt "" + @client.sendTextAsClipboard text + + @_api.getClipboard() + .then (text) => + cb(text) + .catch (e) => + @error __("Unable to paste"), e + #ask for user to enter the text manually + @openDialog("TextDialog", { title: "Paste text"}) + .then (text) => + cb(text) + .catch (err) => @error err.toString(), err + setScale: () -> return unless @client and @client.resolution w = $(@container).width() diff --git a/RemoteDesktop/package.json b/RemoteDesktop/package.json index b2987bd..5281648 100644 --- a/RemoteDesktop/package.json +++ b/RemoteDesktop/package.json @@ -7,7 +7,7 @@ "author": "Dany LE", "email": "contact@iohub.dev" }, - "version":"0.1.9-b", + "version":"0.1.10-b", "dependencies": [], "category":"Internet", "icon": "icon.png", diff --git a/packages.json b/packages.json index 7b7768f..d552959 100644 --- a/packages.json +++ b/packages.json @@ -365,7 +365,7 @@ "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteDesktop/README.md", "category": "Internet", "author": "Dany LE", - "version": "0.1.9-b", + "version": "0.1.10-b", "dependencies": [],"category":"Internet","icon":"icon.png","mimes":["none"], "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteDesktop/build/release/RemoteDesktop.zip" },