diff --git a/LuaPlayground/build/debug/main.js b/LuaPlayground/build/debug/main.js index 9cb6762..5ce093f 100644 --- a/LuaPlayground/build/debug/main.js +++ b/LuaPlayground/build/debug/main.js @@ -1,4 +1,5 @@ (function() { + void 0; var DataViewer, LuaPlayground, PointCloudViewer; DataViewer = class DataViewer { @@ -175,7 +176,7 @@ } - // point clound render + // point clound render render() { var end, j, len, path, ref, start, v; this.drawGrid(20, "#DBDBDB"); // 20 px @@ -204,42 +205,44 @@ } main() { - var me; - me = this; this.datarea = this.find("editorea"); this.output = this.find("output"); this.editor = ace.edit(this.datarea); this.editor.setOptions({ enableBasicAutocompletion: true, enableLiveAutocompletion: true, - fontSize: "10pt" + highlightActiveLine: true, + highlightSelectedWord: true, + behavioursEnabled: true, + wrap: true, + fontSize: "11pt", + showInvisibles: true }); this.editor.getSession().setUseWrapMode(true); this.editor.session.setMode("ace/mode/lua"); this.editor.setTheme("ace/theme/monokai"); - this.on("vboxchange", function() { - return me.editor.resize(); + this.on("vboxchange", () => { + return this.editor.resize(); }); - (this.find("log-clear")).set("onbtclick", function(e) { - return me.log("clean"); + (this.find("log-clear")).set("onbtclick", (e) => { + return this.log("clean"); }); - (this.find("code-run")).set("onbtclick", function(e) { - return me.run(); + (this.find("code-run")).set("onbtclick", (e) => { + return this.run(); }); - (this.find("code-stop")).set("onbtclick", function(e) { - if (me.socket) { - return me.socket.close(); + (this.find("code-stop")).set("onbtclick", (e) => { + if (this.socket) { + return this.socket.close(); } }); this.socket = null; - return this.bindKey("CTRL-R", function() { - return me.run(); + return this.bindKey("CTRL-R", () => { + return this.run(); }); } menu() { - var me, menu; - me = this; + var menu; menu = [ { text: "__(Code)", @@ -250,8 +253,8 @@ shortcut: "C-R" } ], - onmenuselect: function(e) { - return me.run(); + onchildselect: (e) => { + return this.run(); } } ]; @@ -270,39 +273,42 @@ } run() { - var me, value; - me = this; + var value; value = this.editor.getValue().trim(); if (!(value && value !== "")) { return; } - this.socket = this.stream(); - this.socket.onopen = function() { - //send data to server - return me.socket.send(JSON.stringify({ - code: value - })); - }; - this.socket.onmessage = function(e) { - var err, obj; - if (!e.data) { - return; - } - try { - obj = JSON.parse(e.data); - if (!me.view(obj)) { - return me.log("INFO", e.data); + return this.stream().then((s) => { + this.socket = s; + this.socket.onopen = () => { + //send data to server + return this.socket.send(JSON.stringify({ + code: value + })); + }; + this.socket.onmessage = (e) => { + var err, obj; + if (!e.data) { + return; } - } catch (error) { - err = error; - me.log("INFO", e.data); - return console.log(err); - } - }; - return this.socket.onclose = function() { - me.socket = null; - return console.log("socket closed"); - }; + try { + obj = JSON.parse(e.data); + if (!this.view(obj)) { + return this.log("INFO", e.data); + } + } catch (error) { + err = error; + this.log("INFO", e.data); + return console.log(err); + } + }; + return this.socket.onclose = () => { + this.socket = null; + return console.log("socket closed"); + }; + }).catch((e) => { + return this.error(__("Unable to get websocket stream")); + }); } view(obj) { @@ -330,7 +336,7 @@ }; - LuaPlayground.dependencies = ["ace/ace"]; + LuaPlayground.dependencies = ["os://scripts/ace/ace.js"]; this.OS.register("LuaPlayground", LuaPlayground); diff --git a/LuaPlayground/build/release/LuaPlayground.zip b/LuaPlayground/build/release/LuaPlayground.zip new file mode 100644 index 0000000..0087b14 Binary files /dev/null and b/LuaPlayground/build/release/LuaPlayground.zip differ diff --git a/LuaPlayground/coffees/main.coffee b/LuaPlayground/coffees/main.coffee index e6f098c..73e27f8 100644 --- a/LuaPlayground/coffees/main.coffee +++ b/LuaPlayground/coffees/main.coffee @@ -147,38 +147,41 @@ class LuaPlayground extends this.OS.GUI.BaseApplication super "LuaPlayground", args main: () -> - me = @ @datarea = @find "editorea" @output = @find "output" @.editor = ace.edit @datarea @.editor.setOptions { enableBasicAutocompletion: true, enableLiveAutocompletion: true, - fontSize: "10pt" + highlightActiveLine: true, + highlightSelectedWord: true, + behavioursEnabled: true, + wrap: true, + fontSize: "11pt", + showInvisibles: true } @editor.getSession().setUseWrapMode true @editor.session.setMode "ace/mode/lua" @editor.setTheme "ace/theme/monokai" - @on "vboxchange", () -> - me.editor.resize() - (@find "log-clear").set "onbtclick", (e) -> - me.log "clean" - (@find "code-run").set "onbtclick", (e) -> - me.run() + @on "vboxchange", () => + @editor.resize() + (@find "log-clear").set "onbtclick", (e) => + @log "clean" + (@find "code-run").set "onbtclick", (e) => + @run() - (@find "code-stop").set "onbtclick", (e) -> - me.socket.close() if me.socket + (@find "code-stop").set "onbtclick", (e) => + @socket.close() if @socket @socket = null - @bindKey "CTRL-R", () -> me.run() + @bindKey "CTRL-R", () => @run() menu: () -> - me = @ menu = [{ text: "__(Code)", child: [ { text: "__(Run)", dataid: "#{@name}-Run", shortcut: "C-R" } ], - onmenuselect: (e) -> me.run() + onchildselect: (e) => @run() }] menu @@ -190,26 +193,27 @@ class LuaPlayground extends this.OS.GUI.BaseApplication ($ @output).scrollTop @output.scrollHeight run: () -> - me = @ value = @editor.getValue().trim() return unless value and value isnt "" - @socket = @stream() - @socket.onopen = () -> - #send data to server - me.socket.send( JSON.stringify { code: value } ) - - @socket.onmessage = (e) -> - return unless e.data - try - obj = JSON.parse e.data - me.log "INFO", e.data unless me.view obj - catch err - me.log "INFO", e.data - console.log err - - @socket.onclose = () -> - me.socket = null - console.log "socket closed" + @stream().then (s) => + @socket = s + @socket.onopen = () => + #send data to server + @socket.send( JSON.stringify { code: value } ) + + @socket.onmessage = (e) => + return unless e.data + try + obj = JSON.parse e.data + @log "INFO", e.data unless @view obj + catch err + @log "INFO", e.data + console.log err + + @socket.onclose = () => + @socket = null + console.log "socket closed" + .catch (e) => @error __("Unable to get websocket stream") view: (obj) -> return false unless obj and obj.type and @[obj.type] @@ -226,5 +230,5 @@ class LuaPlayground extends this.OS.GUI.BaseApplication cleanup: (e)-> @socket.close() if @socket -LuaPlayground.dependencies = ["ace/ace"] +LuaPlayground.dependencies = ["os://scripts/ace/ace.js"] this.OS.register "LuaPlayground", LuaPlayground diff --git a/LuaPlayground/project.apj b/LuaPlayground/project.apj deleted file mode 100644 index e8e147d..0000000 --- a/LuaPlayground/project.apj +++ /dev/null @@ -1 +0,0 @@ -{"name":"LuaPlayground","root":"home://myws/antosdk-apps/LuaPlayground","css":["css/main.css"],"javascripts":["javascripts/paper-core.min.js"],"coffees":["coffees/main.coffee"],"copies":["assets/scheme.html","package.json","README.md"]} \ No newline at end of file diff --git a/LuaPlayground/project.json b/LuaPlayground/project.json new file mode 100644 index 0000000..abaccc8 --- /dev/null +++ b/LuaPlayground/project.json @@ -0,0 +1,8 @@ +{ + "name": "LuaPlayground", + "root": "home://workspace/antosdk-apps/LuaPlayground", + "css": ["css/main.css"], + "javascripts": ["javascripts/paper-core.min.js"], + "coffees": ["coffees/main.coffee"], + "copies": ["assets/scheme.html", "package.json", "README.md"] +} \ No newline at end of file diff --git a/OpenPage/README.md b/OpenPage/README.md index 9dcf530..d9dfca7 100644 --- a/OpenPage/README.md +++ b/OpenPage/README.md @@ -1,24 +1,14 @@ -# OpenPage -This is an example project, generated by AntOS Development Kit +![](https://os.lxsang.me/repo/OpenPage/OpenPage.png) +# OpenPage: ODT (Open Document Text) editor alpha +**OpenPage** is an AntOS application developed in-browser using AntOSDK. It is a Pure Javascript based rich text editor compatible with Open Document Format. -## Howto - -1. Open the project.apj file with AntOSDK (simply double Click on it) -2. Modify the UI in *assets/scheme.html* -3. Modify application code in *coffees/main.coffee* -4. Modify CSS style in *css/main.css* -5. Other files need to be copied: put in to assets - -## Set up build target - -Click **Menu> Build > Build Option** or simply hit **ALT-Y** - -In the build options dialog, add or remove files that need to be -included into the build - -Click **Save** - -## Build application -* To build: **Menu > Build > Build** or **ALT-C** -* To build and run: **Menu > Build > Build and Run** or **CTRL-R** -* To release: **Menu > Build > Build release** or **ALT-P** \ No newline at end of file +**Feature:** +* Open, view and edit *.odt* documents +* Offer various formatting style to text +* Define and apply paragraph styles +* Insert link, image +* Embeded fonts +* Save documents as ODF format so that it can be compatible with desktop applications like Open Office + +**Credit:** +OpenPage is heavily based on the WebODF javascript library: https://webodf.org \ No newline at end of file diff --git a/OpenPage/assets/OpenPage.md b/OpenPage/assets/OpenPage.md deleted file mode 100644 index d9dfca7..0000000 --- a/OpenPage/assets/OpenPage.md +++ /dev/null @@ -1,14 +0,0 @@ -![](https://os.lxsang.me/repo/OpenPage/OpenPage.png) -# OpenPage: ODT (Open Document Text) editor alpha -**OpenPage** is an AntOS application developed in-browser using AntOSDK. It is a Pure Javascript based rich text editor compatible with Open Document Format. - -**Feature:** -* Open, view and edit *.odt* documents -* Offer various formatting style to text -* Define and apply paragraph styles -* Insert link, image -* Embeded fonts -* Save documents as ODF format so that it can be compatible with desktop applications like Open Office - -**Credit:** -OpenPage is heavily based on the WebODF javascript library: https://webodf.org \ No newline at end of file diff --git a/OpenPage/build/debug/main.js b/OpenPage/build/debug/main.js index 9a9b769..df39f39 100644 --- a/OpenPage/build/debug/main.js +++ b/OpenPage/build/debug/main.js @@ -1,4 +1,5 @@ (function() { + void 0; var FormatDialog, HyperLinkDialog, OpenPage; OpenPage = class OpenPage extends this.OS.GUI.BaseApplication { @@ -114,7 +115,7 @@ newdoc() { var blank; - blank = `${(this.meta().path)}/blank.odt`; + blank = `${this.meta().path}/blank.odt`; return this.open(blank, true); } @@ -1167,7 +1168,119 @@ }; - FormatDialog.scheme = "\n \n
\n \n
\n \n
\n \n
\n
\n \n \n
\n \n \n \n \n \n \n \n \n
\n
\n
\n \n
\n \n
\n \n \n
\n \n \n
\n \n \n
\n \n \n
\n
\n
\n \n
\n \n
\n \n \n
\n \n \n
\n \n \n
\n \n \n
\n
\n \n
\n \n
\n \n
\n \n \n \n \n \n \n \n
\n
\n \n
\n
\n
\n
\n \n
\n \n
\n \n
\n \n \n
\n \n \n
\n
\n
\n \n
\n \n
\n
\n

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce laoreet diam vestibulum massa malesuada quis dignissim libero blandit. Duis sit amet volutpat nisl.

\n
\n
\n
\n \n
\n \n
\n \n
\n \n
\n
\n
\n
"; + FormatDialog.scheme = ` + +
+ +
+ +
+ +
+
+ + +
+ + + + + + + + +
+
+
+ +
+ +
+ + +
+ + +
+ + +
+ + +
+
+
+ +
+ +
+ + +
+ + +
+ + +
+ + +
+
+ +
+ +
+ +
+ + + + + + + +
+
+ +
+
+
+
+ +
+ +
+ +
+ + +
+ + +
+
+
+ +
+ +
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce laoreet diam vestibulum massa malesuada quis dignissim libero blandit. Duis sit amet volutpat nisl.

+
+
+
+ +
+ +
+ +
+ +
+
+
+
`; }).call(this); diff --git a/OpenPage/coffees/main.coffee b/OpenPage/coffees/main.coffee index 4fdd212..4a11b9c 100644 --- a/OpenPage/coffees/main.coffee +++ b/OpenPage/coffees/main.coffee @@ -66,6 +66,7 @@ class OpenPage extends this.OS.GUI.BaseApplication newdoc: () -> blank = "#{@meta().path}/blank.odt" @open blank, true + open: (p,b) -> me = @ @pathAsDataURL(p) diff --git a/OpenPage/project.apj b/OpenPage/project.apj deleted file mode 100644 index 24a8569..0000000 --- a/OpenPage/project.apj +++ /dev/null @@ -1 +0,0 @@ -{"name":"OpenPage","root":"home://workspace/OpenPage","css":["css/main.css","css/dialog.css"],"javascripts":["javascripts/webodf.js","javascripts/EditorSession.js"],"coffees":["coffees/main.coffee","coffees/dialogs.coffee"],"copies":["assets/scheme.html","package.json","assets/OpenPage.md","assets/icon.png","assets/blank.odt"]} \ No newline at end of file diff --git a/OpenPage/project.json b/OpenPage/project.json new file mode 100644 index 0000000..ffd90a5 --- /dev/null +++ b/OpenPage/project.json @@ -0,0 +1,8 @@ +{ + "name": "OpenPage", + "root": "home://workspace/antosdk-apps/OpenPage", + "css": ["css/main.css", "css/dialog.css"], + "javascripts": ["javascripts/webodf.js", "javascripts/EditorSession.js"], + "coffees": ["coffees/main.coffee", "coffees/dialogs.coffee"], + "copies": ["assets/scheme.html", "package.json", "assets/icon.png", "assets/blank.odt"] +} \ No newline at end of file diff --git a/Preview/build/debug/main.css b/Preview/build/debug/main.css index fb523a2..555c20c 100644 --- a/Preview/build/debug/main.css +++ b/Preview/build/debug/main.css @@ -8,20 +8,26 @@ afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-i background-repeat: repeat; } -afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-id = "status"] +afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] { background-color: transparent; - border-top: 1px solid #cbcbcb; - padding-left: 10px; - padding-top: 3px; + border-bottom: 1px solid #cbcbcb; +} +afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] button, +afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] input +{ + height: 24px; } - afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] canvas{ margin-left: auto; margin-right: auto; display: block; } +afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div.pdf-page { + margin-bottom: 5px; +} + afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-id = "view"].image { display: flex; diff --git a/Preview/build/debug/main.js b/Preview/build/debug/main.js index f3aa5c6..62b4600 100644 --- a/Preview/build/debug/main.js +++ b/Preview/build/debug/main.js @@ -25,18 +25,62 @@ } main() { + this.currfile = void 0; if (this.args && this.args.length > 0) { this.currfile = this.args[0].path.asFileHandle(); } this.view = this.find("view"); this.status = this.find("status"); + this.zoom = this.find("zoom"); + this.btnext = this.find("btnext"); + this.btprev = this.find("btprev"); + this.btreset = this.find("btreset"); + this.txtpage = this.find("txtpage"); + this.zoom.set("onchange", (e) => { + return this.setViewScale(e.data); + }); + this.btreset.set("onbtclick", (e) => { + this.zoom.set("value", 100); + return this.setViewScale(100); + }); + this.btnext.set("onbtclick", (e) => { + var val; + val = parseInt($(this.txtpage).val()); + if (isNaN(val)) { + return; + } + $(this.txtpage).val(val + 1); + return this.gotoPage(); + }); + this.btprev.set("onbtclick", (e) => { + var val; + val = parseInt($(this.txtpage).val()); + if (isNaN(val)) { + return; + } + $(this.txtpage).val(val - 1); + return this.gotoPage(); + }); + $(this.txtpage).keyup((e) => { + if (e.which !== 13) { + return; + } + if (!this.pdf) { + return; + } + return this.gotoPage(); + }); PDFJS.workerSrc = `${this.path()}/pdf.worker.js`.asFileHandle().getlink(); + this.pdf = void 0; + this.img = void 0; this.bindKey("ALT-O", () => { return this.actionFile(`${this.name}-Open`); }); this.bindKey("CTRL-X", () => { return this.actionFile(`${this.name}-Close`); }); + this.zoom.set("max", 200); + this.zoom.set("value", 100); return this.open(this.currfile); } @@ -49,25 +93,46 @@ } return file.onready().then(() => { file.info.size = (file.info.size / 1024).toFixed(2); - return this.renderFile(file); + return this.renderFile(); }).catch((err) => { return this.error(__("File not found {0}", file.path), err); }); } - renderFile(file) { - var mime; - mime = file.info.mime; - if (!mime) { + gotoPage() { + var val; + if (!this.pdf) { + return; + } + val = parseInt($(this.txtpage).val()); + if (isNaN(val)) { + return; + } + if (val <= 0 || val > this.pdf.numPages) { return; } ($(this.view)).empty(); + return this.renderPDFPages(val, this.zoom.get("value") / 100, false).catch((e) => { + return this.error(__("Unable to render page {0}", val), e); + }); + } + + renderFile() { + var mime; + mime = this.currfile.info.mime; + if (!mime) { + return; + } + this.pdf = void 0; + this.img = void 0; + ($(this.view)).empty(); + this.zoom.set("value", 100); if (mime.match(/^[^\/]+\/.*pdf.*/g)) { - return this.renderPDF(file); + return this.renderPDF(); } else if (mime.match(/image\/.*svg.*/g)) { - return this.renderSVG(file); + return this.renderSVG(); } else if (mime.match(/image\/.*/g)) { - return this.renderImage(file); + return this.renderImage(); } else { return this.notify(__("Mime type {0} is not supported", file.info.mime)); } @@ -77,44 +142,92 @@ return ($(this.status)).html(t); } - renderPDF(file) { - return this.load(new Promise((resolve, reject) => { + setViewScale(value) { + var canvas, context, h, mime, scale, w; + if (!this.currfile) { + return; + } + mime = this.currfile.info.mime; + scale = value / 100; + if (mime.match(/^[^\/]+\/.*pdf.*/g)) { + if (!this.pdf) { + return; + } + ($(this.view)).empty(); + return this.load(this.renderPDFPages(1, scale)).catch((e) => { + return this.error(__("Unable to set view scale"), e); + }); + } else if (mime.match(/image\/.*svg.*/g)) { + return $($(this.view).children()[0]).css("width", `${Math.round(value)}%`).css("height", `${Math.round(value)}%`); + } else if (mime.match(/image\/.*/g)) { + if (!this.img) { + return; + } + canvas = $(this.view).children()[0]; + context = canvas.getContext('2d'); + w = this.img.width * scale; + h = this.img.height * scale; + canvas.height = h; + canvas.width = w; + context.clearRect(0, 0, canvas.width, canvas.height); + context.scale(scale, scale); + return context.drawImage(this.img, 0, 0); + } + } + + renderPDFPages(n, scale, recursive) { + return new Promise((resolve, reject) => { var status; - status = `${file.info.name} (${file.info.size} Kb)`; - return file.read("binary").then((d) => { + status = `${this.currfile.info.name} (${this.currfile.info.size} Kb)`; + if (n > this.pdf.numPages) { + return resolve(); + } + return this.pdf.getPage(n).then((page) => { + var canvas, context, div, renderContext, viewport; + viewport = page.getViewport(scale); + div = ($("
")).attr("id", "page-" + (page.pageIndex + 1)).attr("scale", scale).addClass("pdf-page"); + ($(this.view)).append(div); + canvas = ($(""))[0]; + div.append(canvas); + context = canvas.getContext('2d'); + canvas.height = viewport.height; + canvas.width = viewport.width; + renderContext = { + canvasContext: context, + viewport: viewport + }; + page.render(renderContext); + page._canvas = canvas; + this.setStatus(`${status} - page ${n}/${this.pdf.numPages} loaded`); + if (recursive) { + return this.renderPDFPages(n + 1, scale, recursive).then(function() { + return resolve(); + }).catch(function(e) { + return reject(e); + }); + } else { + return resolve(); + } + }).catch(function(e) { + return reject(e); + }); + }); + } + + renderPDF() { + return this.load(new Promise((resolve, reject) => { + return this.currfile.read("binary").then((d) => { ($(this.view)).removeClass(); return PDFJS.getDocument({ data: d }).then((pdf) => { - var fn; - fn = (p) => { - if (p > pdf.numPages) { - this.setStatus(`${status} - loaded`); - return resolve(); - } - return pdf.getPage(p).then((page) => { - var canvas, context, div, renderContext, scale, viewport; - scale = 1.5; - viewport = page.getViewport(scale); - div = ($("
")).attr("id", "page-" + (page.pageIndex + 1)); - ($(this.view)).append(div); - canvas = ($(""))[0]; - div.append(canvas); - context = canvas.getContext('2d'); - canvas.height = viewport.height; - canvas.width = viewport.width; - renderContext = { - canvasContext: context, - viewport: viewport - }; - page.render(renderContext); - this.setStatus(`${status} - ${p}/${pdf.numPages} loaded`); - return fn(p + 1); - }).catch(function(e) { - return reject(e); - }); - }; - return fn(1); + this.pdf = pdf; + return this.renderPDFPages(1, 1, false).then(() => { + $(this.txtpage).val("1"); + return resolve(); + }).catch(function(e) { + return reject(e); + }); }).catch(function(e) { return reject(e); }); @@ -122,23 +235,23 @@ return reject(e); }); })).catch((e) => { - return this.error(__("Unable to view file: {}", file.path), e); + return this.error(__("Unable to view file: {0}", this.currfile.path), e); }); } - renderSVG(file) { + renderSVG() { ($(this.view)).attr("class", "image"); - return file.read().then((d) => { + return this.currfile.read().then((d) => { this.view.innerHTML = d; return $($(this.view).children()[0]).css("width", "100%").css("height", "100%"); }).catch((e) => { - return this.error(__("Unable to read file: {}", file.path), e); + return this.error(__("Unable to read file: {0}", this.currfile.path), e); }); } - renderImage(file) { + renderImage() { ($(this.view)).attr("class", "image"); - return file.read("binary").then((d) => { + return this.currfile.read("binary").then((d) => { var blob, canvas, img; img = new Image(); canvas = ($(""))[0]; @@ -149,16 +262,17 @@ context = canvas.getContext('2d'); canvas.height = img.height; canvas.width = img.width; + this.img = img; //console.log canvas.width, canvas.height context.drawImage(img, 0, 0); - return this.setStatus(`${file.info.name} (${file.info.size} Kb) - ${img.width}x${img.height}`); + return this.setStatus(`${this.currfile.info.name} (${this.currfile.info.size} Kb) - ${img.width}x${img.height}`); }; blob = new Blob([d], { - type: file.info.mime + type: this.currfile.info.mime }); return img.src = URL.createObjectURL(blob); }).catch((e) => { - return this.error(__("Unable to read file: {}", file.path), e); + return this.error(__("Unable to read file: {0}", this.currfile.path), e); }); } diff --git a/Preview/build/debug/package.json b/Preview/build/debug/package.json index c39ac21..d7ba2de 100644 --- a/Preview/build/debug/package.json +++ b/Preview/build/debug/package.json @@ -6,7 +6,7 @@ "author": "Xuan Sang LE", "email": "xsang.le@gmail.com" }, - "version":"0.0.2-a", + "version":"0.0.3-a", "category":"Utils", "iconclass":"fa fa-eye", "mimes":["[^\/]*/.*pdf", "image/.*"] diff --git a/Preview/build/debug/scheme.html b/Preview/build/debug/scheme.html index 9213565..3754170 100644 --- a/Preview/build/debug/scheme.html +++ b/Preview/build/debug/scheme.html @@ -1,6 +1,17 @@ + +
+ + + +
+ +
+ +
+
+
-
\ No newline at end of file diff --git a/Preview/build/release/Preview.zip b/Preview/build/release/Preview.zip index d287687..f712249 100644 Binary files a/Preview/build/release/Preview.zip and b/Preview/build/release/Preview.zip differ diff --git a/Preview/main.coffee b/Preview/main.coffee index 36a9e12..4260efa 100644 --- a/Preview/main.coffee +++ b/Preview/main.coffee @@ -21,14 +21,46 @@ class Preview extends this.OS.GUI.BaseApplication super "Preview", args main: () -> + @currfile = undefined @currfile = @args[0].path.asFileHandle() if @args and @args.length > 0 @view = @find "view" @status = @find "status" + @zoom = @find "zoom" + @btnext = @find "btnext" + @btprev = @find "btprev" + @btreset = @find "btreset" + @txtpage = @find "txtpage" + + @zoom.set "onchange", (e) => @setViewScale e.data + + @btreset.set "onbtclick", (e) => + @zoom.set "value", 100 + @setViewScale 100 + + @btnext.set "onbtclick", (e) => + val = parseInt $(@txtpage).val() + return if isNaN val + $(@txtpage).val val + 1 + @gotoPage() + @btprev.set "onbtclick", (e) => + val = parseInt $(@txtpage).val() + return if isNaN val + $(@txtpage).val val - 1 + @gotoPage() + + $(@txtpage).keyup (e) => + return unless e.which is 13 + return unless @pdf + @gotoPage() + PDFJS.workerSrc = "#{@path()}/pdf.worker.js".asFileHandle().getlink() + @pdf = undefined + @img = undefined @bindKey "ALT-O", () => @actionFile "#{@name}-Open" @bindKey "CTRL-X", () => @actionFile "#{@name}-Close" - + @zoom.set "max", 200 + @zoom.set "value", 100 @open @currfile @@ -37,72 +69,125 @@ class Preview extends this.OS.GUI.BaseApplication @currfile = file unless @currfile is file file.onready().then () => file.info.size = (file.info.size / 1024).toFixed(2) - @renderFile file + @renderFile() .catch (err) => @error __("File not found {0}", file.path), err - renderFile: (file) -> - mime = file.info.mime - return unless mime + + gotoPage: () -> + return unless @pdf + val = parseInt $(@txtpage).val() + return if isNaN(val) + return if val <= 0 or val > @pdf.numPages ($ @view).empty() + @renderPDFPages val, (@zoom.get("value") / 100), false + .catch (e) => @error __("Unable to render page {0}", val), e + + renderFile: () -> + mime = @currfile.info.mime + return unless mime + @pdf = undefined + @img = undefined + ($ @view).empty() + @zoom.set "value", 100 if mime.match /^[^\/]+\/.*pdf.*/g - @renderPDF file + @renderPDF() else if mime.match /image\/.*svg.*/g - @renderSVG file + @renderSVG() else if mime.match /image\/.*/g - @renderImage file + @renderImage() else @notify __("Mime type {0} is not supported", file.info.mime) setStatus: (t) -> ($ @status).html t - renderPDF: (file) -> + setViewScale: (value) -> + return unless @currfile + mime = @currfile.info.mime + scale = (value / 100) + if mime.match /^[^\/]+\/.*pdf.*/g + return unless @pdf + ($ @view).empty() + @load @renderPDFPages 1, scale + .catch (e) => @error __("Unable to set view scale"), e + + else if mime.match /image\/.*svg.*/g + $($(@view).children()[0]) + .css "width", "#{Math.round(value)}%" + .css "height", "#{Math.round(value)}%" + + else if mime.match /image\/.*/g + return unless @img + canvas = $(@view).children()[0] + context = canvas.getContext '2d' + w = @img.width * scale + h = @img.height * scale + canvas.height = h + canvas.width = w + context.clearRect(0, 0, canvas.width, canvas.height) + context.scale scale, scale + context.drawImage @img, 0, 0 + + renderPDFPages: (n, scale, recursive) -> + new Promise (resolve, reject) => + status = "#{@currfile.info.name} (#{@currfile.info.size} Kb)" + return resolve() if n > @pdf.numPages + @pdf.getPage(n).then (page) => + viewport = page.getViewport scale + div = ($ "
") + .attr("id", "page-" + (page.pageIndex + 1)) + .attr("scale", scale) + .addClass "pdf-page" + ($ @view).append div + canvas = ($ "")[0] + div.append canvas + context = canvas.getContext '2d' + canvas.height = viewport.height + canvas.width = viewport.width + renderContext = + canvasContext: context + viewport: viewport + page.render renderContext + page._canvas = canvas + @setStatus "#{status} - page #{n}/#{@pdf.numPages} loaded" + if recursive + @renderPDFPages n + 1, scale, recursive + .then () -> resolve() + .catch (e) -> reject e + else + resolve() + .catch (e) -> reject e + + renderPDF: () -> @load new Promise (resolve, reject) => - status = "#{file.info.name} (#{file.info.size} Kb)" - file.read("binary").then (d) => + @currfile.read("binary").then (d) => ($ @view).removeClass() PDFJS.getDocument { data: d } .then (pdf) => - fn = (p) => - if p > pdf.numPages - @setStatus "#{status} - loaded" - return resolve() - pdf.getPage(p).then (page) => - scale = 1.5 - viewport = page.getViewport scale - div = ($ "
").attr("id", "page-" + (page.pageIndex + 1)) - ($ @view).append div - canvas = ($ "")[0] - div.append canvas - context = canvas.getContext '2d' - canvas.height = viewport.height - canvas.width = viewport.width - renderContext = - canvasContext: context - viewport: viewport - page.render renderContext - @setStatus "#{status} - #{p}/#{pdf.numPages} loaded" - fn(p+1) + @pdf = pdf + @renderPDFPages 1, 1, false + .then () => + $(@txtpage).val("1") + resolve() .catch (e) -> reject e - fn(1) .catch (e) -> reject e .catch (e) -> reject e - .catch (e) => @error __("Unable to view file: {}", file.path), e + .catch (e) => @error __("Unable to view file: {0}", @currfile.path), e - renderSVG: (file) -> + renderSVG: () -> ($ @view).attr("class", "image") - file.read().then (d) => + @currfile.read().then (d) => @view.innerHTML = d $($(@view).children()[0]) .css "width", "100%" .css "height", "100%" - .catch (e) => @error __("Unable to read file: {}", file.path), e + .catch (e) => @error __("Unable to read file: {0}", @currfile.path), e - renderImage: (file) -> + renderImage: () -> ($ @view).attr("class", "image") - file.read("binary").then (d) => + @currfile.read("binary").then (d) => img = new Image() canvas = ($ "")[0] ($ @view).append canvas @@ -112,13 +197,14 @@ class Preview extends this.OS.GUI.BaseApplication context = canvas.getContext '2d' canvas.height = img.height canvas.width = img.width + @img = img #console.log canvas.width, canvas.height context.drawImage img, 0, 0 - @setStatus "#{file.info.name} (#{file.info.size} Kb) - #{img.width}x#{img.height}" + @setStatus "#{@currfile.info.name} (#{@currfile.info.size} Kb) - #{img.width}x#{img.height}" - blob = new Blob [d], { type: file.info.mime } + blob = new Blob [d], { type: @currfile.info.mime } img.src = URL.createObjectURL blob - .catch (e) => @error __("Unable to read file: {}", file.path), e + .catch (e) => @error __("Unable to read file: {0}", @currfile.path), e menu: () -> menu = [{ diff --git a/Preview/main.css b/Preview/main.css index a2f8dc4..c2b3e9d 100644 --- a/Preview/main.css +++ b/Preview/main.css @@ -7,20 +7,26 @@ afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-i background-repeat: repeat; } -afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-id = "status"] +afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] { background-color: transparent; - border-top: 1px solid #cbcbcb; - padding-left: 10px; - padding-top: 3px; + border-bottom: 1px solid #cbcbcb; +} +afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] button, +afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] afx-hbox[data-id = "statcontainer"] input +{ + height: 24px; } - afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] canvas{ margin-left: auto; margin-right: auto; display: block; } +afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div.pdf-page { + margin-bottom: 5px; +} + afx-app-window[data-id = "preview-win"] afx-vbox[data-id="container"] div[data-id = "view"].image { display: flex; diff --git a/Preview/package.json b/Preview/package.json index c39ac21..d7ba2de 100644 --- a/Preview/package.json +++ b/Preview/package.json @@ -6,7 +6,7 @@ "author": "Xuan Sang LE", "email": "xsang.le@gmail.com" }, - "version":"0.0.2-a", + "version":"0.0.3-a", "category":"Utils", "iconclass":"fa fa-eye", "mimes":["[^\/]*/.*pdf", "image/.*"] diff --git a/Preview/scheme.html b/Preview/scheme.html index 9213565..3754170 100644 --- a/Preview/scheme.html +++ b/Preview/scheme.html @@ -1,6 +1,17 @@ + +
+ + + +
+ +
+ +
+
+
-
\ No newline at end of file diff --git a/TinyEditor/README.md b/TinyEditor/README.md index 90199f5..5797927 100644 --- a/TinyEditor/README.md +++ b/TinyEditor/README.md @@ -1,24 +1,3 @@ # TinyEditor This is the example project for the tutorial: [https://blog.lxsang.me/post/id/20](https://blog.lxsang.me/post/id/20) -## Howto - -1. Open the project.apj file with AntOSDK (simply double Click on it) -2. Modify the UI in *assets/scheme.html* -3. Modify application code in *coffees/main.coffee* -4. Modify CSS style in *css/main.css* -5. Other files need to be copied: put in to assets - -## Set up build target - -Click **Menu> Build > Build Option** or simply hit **ALT-Y** - -In the build options dialog, add or remove files that need to be -included into the build - -Click **Save** - -## Build application -* To build: **Menu > Build > Build** or **ALT-C** -* To build and run: **Menu > Build > Build and Run** or **CTRL-R** -* To release: **Menu > Build > Build release** or **ALT-P** diff --git a/TinyEditor/build/debug/README.md b/TinyEditor/build/debug/README.md index 90199f5..5797927 100644 --- a/TinyEditor/build/debug/README.md +++ b/TinyEditor/build/debug/README.md @@ -1,24 +1,3 @@ # TinyEditor This is the example project for the tutorial: [https://blog.lxsang.me/post/id/20](https://blog.lxsang.me/post/id/20) -## Howto - -1. Open the project.apj file with AntOSDK (simply double Click on it) -2. Modify the UI in *assets/scheme.html* -3. Modify application code in *coffees/main.coffee* -4. Modify CSS style in *css/main.css* -5. Other files need to be copied: put in to assets - -## Set up build target - -Click **Menu> Build > Build Option** or simply hit **ALT-Y** - -In the build options dialog, add or remove files that need to be -included into the build - -Click **Save** - -## Build application -* To build: **Menu > Build > Build** or **ALT-C** -* To build and run: **Menu > Build > Build and Run** or **CTRL-R** -* To release: **Menu > Build > Build release** or **ALT-P** diff --git a/TinyEditor/build/debug/main.css b/TinyEditor/build/debug/main.css index 5b61782..c217986 100644 --- a/TinyEditor/build/debug/main.css +++ b/TinyEditor/build/debug/main.css @@ -1,8 +1,6 @@ afx-app-window[data-id="TinyEditor"] textarea[data-id="editor"] { - background-color: #272822; - color:white; margin: 0; padding:10px; border: 0; diff --git a/TinyEditor/build/debug/main.js b/TinyEditor/build/debug/main.js index 420f31a..f2179be 100644 --- a/TinyEditor/build/debug/main.js +++ b/TinyEditor/build/debug/main.js @@ -1,4 +1,5 @@ (function() { + void 0; var TinyEditor; TinyEditor = class TinyEditor extends this.OS.GUI.BaseApplication { @@ -7,32 +8,29 @@ } main() { - var me; - me = this; this.editor = this.find("editor"); - this.bindKey("ALT-N", function() { - return me.newFile(); + this.bindKey("ALT-N", () => { + return this.newFile(); }); - this.bindKey("ALT-O", function() { - return me.openFile(); + this.bindKey("ALT-O", () => { + return this.openFile(); }); - this.bindKey("CTRL-S", function() { - return me.saveFile(); + this.bindKey("CTRL-S", () => { + return this.saveFile(); }); - this.filehandler = this.args && this.args.length > 0 ? this.args[0].asFileHandler() : null; - $(this.editor).on('input', function(e) { - if (me.filehandler.dirty === true) { + this.filehandle = this.args && this.args.length > 0 ? this.args[0].asFileHandle() : null; + $(this.editor).on('input', (e) => { + if (this.filehandle.dirty === true) { return; } - me.filehandler.dirty = true; - return me.scheme.set("apptitle", `${me.filehandler.path}*`); + this.filehandle.dirty = true; + return this.scheme.set("apptitle", `${this.filehandle.path}*`); }); return this.read(); } menu() { - var m, me; - me = this; + var m; m = [ { text: "__(File)", @@ -53,14 +51,14 @@ shortcut: 'C-S' } ], - onmenuselect: function(e) { - switch (e.item.data.dataid) { + onchildselect: (e) => { + switch (e.data.item.get("data").dataid) { case "new": - return me.newFile(); + return this.newFile(); case "open": - return me.openFile(); + return this.openFile(); case "save": - return me.saveFile(); + return this.saveFile(); } } } @@ -69,71 +67,73 @@ } newFile() { - this.filehandler = null; + this.filehandle = null; return this.read(); } openFile() { - var me; - me = this; - return this.openDialog("FileDiaLog", function(dir, fname, d) { - me.filehandler = `${dir}/${fname}`.asFileHandler(); - return me.read(); - }, __("Open file")); + return this.openDialog("FileDialog", { + title: __("Open file") + }).then((d) => { + this.filehandle = d.file.path.asFileHandle(); + return this.read(); + }); } saveFile() { - var me; - me = this; - this.filehandler.cache = this.editor.value; - if (this.filehandler.path !== "Untitled") { + this.filehandle.cache = this.editor.value; + if (this.filehandle.path !== "Untitled") { return this.write(); } - return this.openDialog("FileDiaLog", function(dir, fname, d) { - me.filehandler.setPath(`${dir}/${fname}`); - return me.write(); - }, __("Save as"), { - file: me.filehandler + return this.openDialog("FileDialog", { + title: __("Save as"), + file: this.filehandle + }).then((f) => { + var d; + d = f.file.path.asFileHandle(); + if (f.file.type === "file") { + d = d.parent(); + } + this.filehandle.setPath(`${d.path}/${f.name}`); + return this.write(); }); } read() { - var me; - me = this; this.editor.value = ""; - if (this.filehandler === null) { - this.filehandler = "Untitled".asFileHandler(); + if (this.filehandle === null) { + this.filehandle = "Untitled".asFileHandle(); this.scheme.set("apptitle", "Untitled"); return; } - return this.filehandler.read(function(d) { - me.scheme.set("apptitle", me.filehandler.path); - return me.editor.value = d; + return this.filehandle.read().then((d) => { + this.scheme.set("apptitle", this.filehandle.path); + return this.editor.value = d; + }).catch((e) => { + return this.error(__("Unable to read file content")); }); } write() { - var me; - me = this; - return this.filehandler.write("text/plain", function(d) { - if (d.error) { - return me.error(__("Error saving file {0}", me.filehandler.path)); - } - me.filehandler.dirty = false; - return me.scheme.set("apptitle", `${me.filehandler.path}`); + return this.filehandle.write("text/plain").then((d) => { + this.filehandle.dirty = false; + return this.scheme.set("apptitle", `${this.filehandle.path}`); + }).catch((e) => { + return this.error(__("Error saving file {0}", this.filehandle.path), e); }); } cleanup(e) { - var me; - if (!this.filehandler.dirty) { + if (!this.filehandle.dirty) { return; } - me = this; e.preventDefault(); - return this.ask("__(Quit)", "__(Quit without saving?)", function() { - me.filehandler.dirty = false; - return me.quit(); + return this.ask({ + title: "__(Quit)", + text: "__(Quit without saving?)" + }).then(() => { + this.filehandle.dirty = false; + return this.quit(); }); } diff --git a/TinyEditor/build/debug/package.json b/TinyEditor/build/debug/package.json index 8ea9640..7889034 100644 --- a/TinyEditor/build/debug/package.json +++ b/TinyEditor/build/debug/package.json @@ -1,10 +1,10 @@ { "app":"TinyEditor", - "name":"TinyEditor", - "description":"", + "name":"Tiny editor", + "description":"Basic plain text file editor", "info":{ - "author": "", - "email": "" + "author": "Xuan Sang LE", + "email": "xsang.le@gmail.com" }, "version":"0.0.1-a", "category":"Other", diff --git a/TinyEditor/build/release/TinyEditor.zip b/TinyEditor/build/release/TinyEditor.zip new file mode 100644 index 0000000..a08cf32 Binary files /dev/null and b/TinyEditor/build/release/TinyEditor.zip differ diff --git a/TinyEditor/coffees/main.coffee b/TinyEditor/coffees/main.coffee index c82e5be..dd394a7 100644 --- a/TinyEditor/coffees/main.coffee +++ b/TinyEditor/coffees/main.coffee @@ -3,20 +3,18 @@ class TinyEditor extends this.OS.GUI.BaseApplication super "TinyEditor", args main: () -> - me = @ @editor = @find "editor" - @bindKey "ALT-N", () -> me.newFile() - @bindKey "ALT-O", () -> me.openFile() - @bindKey "CTRL-S", () -> me.saveFile() - @filehandler = if @args and @args.length > 0 then @args[0].asFileHandler() else null - $(@editor).on 'input', (e) -> - return if me.filehandler.dirty is true - me.filehandler.dirty = true - me.scheme.set "apptitle", "#{me.filehandler.path}*" + @bindKey "ALT-N", () => @newFile() + @bindKey "ALT-O", () => @openFile() + @bindKey "CTRL-S", () => @saveFile() + @filehandle = if @args and @args.length > 0 then @args[0].asFileHandle() else null + $(@editor).on 'input', (e) => + return if @filehandle.dirty is true + @filehandle.dirty = true + @scheme.set "apptitle", "#{@filehandle.path}*" @read() menu: () -> - me = @ m = [ { text: "__(File)", @@ -25,60 +23,62 @@ class TinyEditor extends this.OS.GUI.BaseApplication { text: "__(Open)", dataid :"open", shortcut: 'A-O' }, { text: "__(Save)", dataid :"save", shortcut: 'C-S' } ], - onmenuselect: (e) -> - switch e.item.data.dataid - when "new" then me.newFile() - when "open" then me.openFile() - when "save" then me.saveFile() + onchildselect: (e) => + switch e.data.item.get("data").dataid + when "new" then @newFile() + when "open" then @openFile() + when "save" then @saveFile() } ] m newFile: () -> - @filehandler = null + @filehandle = null @read() openFile: () -> - me = @ - @openDialog "FileDiaLog", ( dir, fname, d ) -> - me.filehandler = "#{dir}/#{fname}".asFileHandler() - me.read() - , __("Open file") + @openDialog "FileDialog", { title: __("Open file") } + .then (d) => + @filehandle = d.file.path.asFileHandle() + @read() + , saveFile: () -> - me = @ - @filehandler.cache = @editor.value - return @write() unless @filehandler.path is "Untitled" - @openDialog "FileDiaLog", (dir, fname, d) -> - me.filehandler.setPath "#{dir}/#{fname}" - me.write() - , __("Save as"), { file: me.filehandler } + @filehandle.cache = @editor.value + return @write() unless @filehandle.path is "Untitled" + @openDialog("FileDialog", { + title: __("Save as"), + file: @filehandle + }).then (f) => + d = f.file.path.asFileHandle() + d = d.parent() if f.file.type is "file" + @filehandle.setPath "#{d.path}/#{f.name}" + @write() read: () -> - me = @ @editor.value = "" - if @filehandler is null - @filehandler = "Untitled".asFileHandler() + if @filehandle is null + @filehandle = "Untitled".asFileHandle() @scheme.set "apptitle", "Untitled" return - @filehandler.read (d) -> - me.scheme.set "apptitle", me.filehandler.path - me.editor.value = d + @filehandle.read().then (d) => + @scheme.set "apptitle", @filehandle.path + @editor.value = d + .catch (e) => @error __("Unable to read file content") write: () -> - me = @ - @filehandler.write "text/plain", (d) -> - return me.error __("Error saving file {0}", me.filehandler.path) if d.error - me.filehandler.dirty = false - me.scheme.set "apptitle", "#{me.filehandler.path}" + @filehandle.write("text/plain").then (d) => + @filehandle.dirty = false + @scheme.set "apptitle", "#{@filehandle.path}" + .catch (e) => @error __("Error saving file {0}", @filehandle.path), e cleanup: (e) -> - return unless @filehandler.dirty - me = @ + return unless @filehandle.dirty e.preventDefault() - @ask "__(Quit)", "__(Quit without saving?)", () -> - me.filehandler.dirty = false - me.quit() + @ask { title: "__(Quit)", text: "__(Quit without saving?)" } + .then () => + @filehandle.dirty = false + @quit() this.OS.register "TinyEditor", TinyEditor \ No newline at end of file diff --git a/TinyEditor/css/main.css b/TinyEditor/css/main.css index 15a6b1d..5ffe5f0 100644 --- a/TinyEditor/css/main.css +++ b/TinyEditor/css/main.css @@ -1,7 +1,5 @@ afx-app-window[data-id="TinyEditor"] textarea[data-id="editor"] { - background-color: #272822; - color:white; margin: 0; padding:10px; border: 0; diff --git a/TinyEditor/package.json b/TinyEditor/package.json index 8ea9640..7889034 100644 --- a/TinyEditor/package.json +++ b/TinyEditor/package.json @@ -1,10 +1,10 @@ { "app":"TinyEditor", - "name":"TinyEditor", - "description":"", + "name":"Tiny editor", + "description":"Basic plain text file editor", "info":{ - "author": "", - "email": "" + "author": "Xuan Sang LE", + "email": "xsang.le@gmail.com" }, "version":"0.0.1-a", "category":"Other", diff --git a/TinyEditor/project.apj b/TinyEditor/project.apj deleted file mode 100644 index 5afdd5d..0000000 --- a/TinyEditor/project.apj +++ /dev/null @@ -1 +0,0 @@ -{"name":"TinyEditor","root":"home://workspace/TinyEditor","css":["css/main.css"],"javascripts":[],"coffees":["coffees/main.coffee"],"copies":["assets/scheme.html","package.json","README.md"]} \ No newline at end of file diff --git a/TinyEditor/project.json b/TinyEditor/project.json new file mode 100644 index 0000000..63c3589 --- /dev/null +++ b/TinyEditor/project.json @@ -0,0 +1,8 @@ +{ + "name": "TinyEditor", + "root": "home://workspace/antosdk-apps/TinyEditor", + "css": ["css/main.css"], + "javascripts": [], + "coffees": ["coffees/main.coffee"], + "copies": ["assets/scheme.html", "package.json", "README.md"] +} \ No newline at end of file diff --git a/packages.json b/packages.json index 33232c8..f8a26e4 100644 --- a/packages.json +++ b/packages.json @@ -17,6 +17,15 @@ "version": "0.0.1-a", "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/ActivityMonitor/build/release/ActivityMonitor.zip" }, + { + "pkgname": "LuaPlayground", + "name": "LuaPlayground", + "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/LuaPlayground/README.md", + "category": "System", + "author": "Xuan Sang LEs", + "version": "0.0.1-a", + "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/LuaPlayground/build/release/LuaPlayground.zip" + }, { "pkgname": "MarkOn", "name": "Markdown editor", @@ -32,7 +41,7 @@ "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Preview/README.md", "category": "Utils", "author": "Xuan Sang LE", - "version": "0.0.2-a", + "version": "0.0.3-a", "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Preview/build/release/Preview.zip" }, { @@ -44,6 +53,15 @@ "version": "0.0.2-a", "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/ShowCase/build/release/ShowCase.zip" }, + { + "pkgname": "TinyEditor", + "name": "Tiny editor", + "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/TinyEditor/README.md", + "category": "Other", + "author": "Xuan Sang LE", + "version": "0.0.1-a", + "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/TinyEditor/build/release/TinyEditor.zip" + }, { "pkgname": "wTerm", "name": "Terminal",