mirror of
https://github.com/lxsang/antos-frontend.git
synced 2024-11-19 10:58:20 +01:00
add market place
This commit is contained in:
parent
d1e8fd91dc
commit
ff6f480f08
5
Makefile
5
Makefile
@ -49,10 +49,7 @@ coffees= src/core/core.coffee \
|
|||||||
src/core/tags/SystemPanelTag.coffee \
|
src/core/tags/SystemPanelTag.coffee \
|
||||||
src/antos.coffee
|
src/antos.coffee
|
||||||
|
|
||||||
|
packages = CoreServices Files Setting CodePad MarketPlace
|
||||||
|
|
||||||
|
|
||||||
packages = CoreServices Files Setting CodePad
|
|
||||||
|
|
||||||
main: initd build_coffees build_themes libs build_packages languages
|
main: initd build_coffees build_themes libs build_packages languages
|
||||||
- cp src/index.html $(BUILDDIR)/
|
- cp src/index.html $(BUILDDIR)/
|
||||||
|
@ -290,7 +290,7 @@ SelectionDialog.scheme = """
|
|||||||
<afx-hbox data-height="30">
|
<afx-hbox data-height="30">
|
||||||
<div />
|
<div />
|
||||||
<afx-button data-id = "btnOk" text = "__(Ok)" data-width = "40" />
|
<afx-button data-id = "btnOk" text = "__(Ok)" data-width = "40" />
|
||||||
<afx-button data-id = "btnCancel" text = "__(Cancels)" data-width = "50" />
|
<afx-button data-id = "btnCancel" text = "__(Cancel)" data-width = "50" />
|
||||||
</afx-hbox>
|
</afx-hbox>
|
||||||
</afx-vbox>
|
</afx-vbox>
|
||||||
<div data-width = "10" />
|
<div data-width = "10" />
|
||||||
|
@ -208,11 +208,11 @@ Ant.OS.API =
|
|||||||
r.responseType = "arraybuffer"
|
r.responseType = "arraybuffer"
|
||||||
r.onload = (e) ->
|
r.onload = (e) ->
|
||||||
if @status is 200 and @readyState is 4
|
if @status is 200 and @readyState is 4
|
||||||
resolve @response
|
|
||||||
Ant.OS.API.loaded q, p, "OK"
|
Ant.OS.API.loaded q, p, "OK"
|
||||||
|
resolve @response
|
||||||
else
|
else
|
||||||
reject e, @
|
|
||||||
Ant.OS.API.loaded q, p, "FAIL"
|
Ant.OS.API.loaded q, p, "FAIL"
|
||||||
|
reject Ant.OS.API.throwe __("Unable to get blob: {0}", p)
|
||||||
Ant.OS.API.loading q, p
|
Ant.OS.API.loading q, p
|
||||||
r.send()
|
r.send()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"app":"{0}",
|
"app":"{0}",
|
||||||
"name":"{0}",
|
"name":"{0}",
|
||||||
"description":"",
|
"description":"{0}",
|
||||||
"info":{
|
"info":{
|
||||||
"author": "",
|
"author": "",
|
||||||
"email": ""
|
"email": ""
|
||||||
|
@ -16,78 +16,67 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
#along with this program. If not, see https://www.gnu.org/licenses/.
|
#along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
|
||||||
class RepositoryDialog extends this.OS.GUI.BaseDialog
|
class RepositoryDialog extends this.OS.GUI.subwindows.SelectionDialog
|
||||||
constructor: () ->
|
constructor: () ->
|
||||||
super "RepositoryDialog"
|
super()
|
||||||
|
|
||||||
init: () ->
|
|
||||||
@_gui.htmlToScheme RepositoryDialog.scheme, @, @host
|
|
||||||
#@render "#{@meta().path}/repositorydia.html"
|
|
||||||
|
|
||||||
main: () ->
|
main: () ->
|
||||||
me = @
|
@list = @find "list"
|
||||||
@list = @find "repo-list"
|
$((@find "btnOk")).hide()
|
||||||
@list.set "onlistdbclick", (e) ->
|
|
||||||
selidx = me.list.get "selidx"
|
|
||||||
return unless selidx >= 0
|
|
||||||
sel = me.systemsetting.system.repositories[selidx]
|
|
||||||
me.openDialog "PromptDialog", (e) ->
|
|
||||||
m = e.match /\[([^\]]*)\]\s*(.*)/
|
|
||||||
return me.error "Wrong format: it should be [name] url" if not m or m.length isnt 3
|
|
||||||
sel.name = m[1]
|
|
||||||
sel.text = sel.name
|
|
||||||
sel.url = m[2]
|
|
||||||
me.refreshList()
|
|
||||||
, __("Edit repository"), { label: __("Format : [name] url"), value: "[#{e.data.text}] #{e.data.url}" }
|
|
||||||
|
|
||||||
@list.set "buttons", [
|
@list.set "buttons", [
|
||||||
{
|
{
|
||||||
text: "+",
|
text: "+",
|
||||||
onbtclick: () ->
|
onbtclick: () =>
|
||||||
me.openDialog "PromptDialog", (e) ->
|
@openDialog("PromptDialog", {
|
||||||
m = e.match /\[([^\]]*)\]\s*(.*)/
|
title: __("Add repository"),
|
||||||
return me.error __("Wrong format: it should be [name] url") if not m or m.length isnt 3
|
label: __("Format : [name] url")
|
||||||
me.systemsetting.system.repositories.push {
|
}).then (e) =>
|
||||||
name: m[1],
|
m = e.match /\[([^\]]*)\]\s*(.+)/
|
||||||
|
if not m or m.length isnt 3
|
||||||
|
return @error __("Wrong format: it should be [name] url")
|
||||||
|
repo = {
|
||||||
url: m[2],
|
url: m[2],
|
||||||
text: m[1],
|
text: m[1]
|
||||||
i: me.systemsetting.system.repositories.length
|
|
||||||
}
|
}
|
||||||
me.refreshList()
|
@systemsetting.system.repositories.push repo
|
||||||
, __("Add repository"), { label: __("Format : [name] url") }
|
@list.push repo
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "-",
|
text: "-",
|
||||||
onbtclick: () ->
|
onbtclick: () =>
|
||||||
selidx = me.list.get "selidx"
|
el = @list.get "selectedItem"
|
||||||
|
return unless el
|
||||||
|
selidx = $(el).index()
|
||||||
return unless selidx >= 0
|
return unless selidx >= 0
|
||||||
me.systemsetting.system.repositories.splice selidx, selidx
|
@systemsetting.system.repositories.splice selidx, selidx
|
||||||
me.refreshList()
|
@list.remove el
|
||||||
|
},
|
||||||
|
{
|
||||||
|
iconclass: "fa fa-pencil",
|
||||||
|
onbtclick: () => @editRepo()
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
(@find "btquit").set "onbtclick", (e) -> me.quit()
|
editRepo: () ->
|
||||||
@refreshList()
|
el = @list.get "selectedItem"
|
||||||
refreshList: () ->
|
return unless el
|
||||||
ls = ({
|
selidx = $(el).index()
|
||||||
text: v.name,
|
return unless selidx >= 0
|
||||||
iconclass: "fa fa-link",
|
data = el.get "data"
|
||||||
url: v.url,
|
sel = @systemsetting.system.repositories[selidx]
|
||||||
complex: true,
|
@openDialog("PromptDialog", {
|
||||||
detail: [{ text: v.url }]
|
title: __("Edit repository"),
|
||||||
} for v in @systemsetting.system.repositories)
|
label: __("Format : [name] url"),
|
||||||
@list.set "items", ls
|
value: "[#{data.text}] #{data.url}"
|
||||||
|
}).then (e) =>
|
||||||
|
m = e.match /\[([^\]]*)\]\s*(.+)/
|
||||||
|
if not m or m.length isnt 3
|
||||||
|
return @error __("Wrong format: it should be [name] url")
|
||||||
|
data.text = m[1]
|
||||||
|
data.url = m[2]
|
||||||
|
@list.update()
|
||||||
|
@list.unselect()
|
||||||
|
|
||||||
onexit: (e) ->
|
onexit: (e) ->
|
||||||
@parent.repo.set "items", @systemsetting.system.repositories
|
@parent.refreshRepoList()
|
||||||
@parent.dialog = undefined if @parent
|
super.onexit e
|
||||||
RepositoryDialog.scheme = """
|
|
||||||
<afx-app-window data-id = "repository-dialog-win" apptitle="__(Repositories)" width="250" height="250">
|
|
||||||
<afx-vbox >
|
|
||||||
<afx-list-view data-id="repo-list"></afx-list-view>
|
|
||||||
<div style = "text-align:right; padding:5px" data-height="30" >
|
|
||||||
<afx-button data-id = "btquit" text = "__(Cancel)"></afx-button>
|
|
||||||
</div>
|
|
||||||
</afx-vbox>
|
|
||||||
</afx-app-window>
|
|
||||||
"""
|
|
@ -16,25 +16,27 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
#along with this program. If not, see https://www.gnu.org/licenses/.
|
#along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
|
||||||
self = this
|
|
||||||
class MarketPlace extends this.OS.GUI.BaseApplication
|
class MarketPlace extends this.OS.GUI.BaseApplication
|
||||||
constructor: (args) ->
|
constructor: (args) ->
|
||||||
super "MarketPlace", args
|
super "MarketPlace", args
|
||||||
|
|
||||||
main: () ->
|
main: () ->
|
||||||
me = @
|
|
||||||
@installdir = @systemsetting.system.pkgpaths.user
|
@installdir = @systemsetting.system.pkgpaths.user
|
||||||
# test repository
|
# test repository
|
||||||
|
@apps_meta = []
|
||||||
@repo = @find "repo"
|
@repo = @find "repo"
|
||||||
@repo.set "onlistselect", (e) ->
|
@repo.set "onlistselect", (e) =>
|
||||||
return unless e.data
|
data = e.data.item.get("data")
|
||||||
me.fetchApps e.data.url
|
return unless data
|
||||||
@repo.set "items", @systemsetting.system.repositories
|
@fetchApps data
|
||||||
|
|
||||||
|
@refreshRepoList()
|
||||||
|
|
||||||
@applist = @find "applist"
|
@applist = @find "applist"
|
||||||
@applist.set "onlistselect", (e) ->
|
@applist.set "onlistselect", (e) =>
|
||||||
return unless e.data
|
data = e.data.item.get("data")
|
||||||
me.appDetail e.data
|
@appDetail data
|
||||||
|
|
||||||
@container = @find "container"
|
@container = @find "container"
|
||||||
@appname = @find "appname"
|
@appname = @find "appname"
|
||||||
@appdesc = @find "app-desc"
|
@appdesc = @find "app-desc"
|
||||||
@ -42,39 +44,105 @@ class MarketPlace extends this.OS.GUI.BaseApplication
|
|||||||
@btinstall = @find "bt-install"
|
@btinstall = @find "bt-install"
|
||||||
@btremove = @find "bt-remove"
|
@btremove = @find "bt-remove"
|
||||||
@btexec = @find "bt-exec"
|
@btexec = @find "bt-exec"
|
||||||
($ @container ).css "visibility", "hidden"
|
@searchbox = @find "searchbox"
|
||||||
@btexec.set "onbtclick", (e) ->
|
($ @container).css "visibility", "hidden"
|
||||||
app = me.applist.get "selected"
|
@btexec.set "onbtclick", (e) =>
|
||||||
return unless app
|
el = @applist.get "selectedItem"
|
||||||
me._gui.launch app.className if app.className
|
return unless el
|
||||||
@btinstall.set "onbtclick", (e) ->
|
app = el.get("data")
|
||||||
return me.update() if me.btinstall.get "dirty"
|
@_gui.launch app.className if app.className
|
||||||
me.install()
|
|
||||||
@btremove.set "onbtclick", (e) ->
|
@btinstall.set "onbtclick", (e) =>
|
||||||
me.uninstall()
|
if @btinstall.get "dirty"
|
||||||
@bindKey "CTRL-R", () ->
|
return @update()
|
||||||
me.openDialog new RepositoryDialog()
|
.then () => @notify __("Package updated")
|
||||||
fetchApps: (url) ->
|
.catch (e) => @error e.toString(), e
|
||||||
me = @
|
@remoteInstall()
|
||||||
@_api.get url, ( d ) ->
|
.then () => @notify __("Package installed")
|
||||||
for v in d
|
.catch (e) => @error e.toString(), e
|
||||||
v.text = v.name
|
|
||||||
v.iconclass = "fa fa-adn"
|
@btremove.set "onbtclick", (e) =>
|
||||||
me.applist.set "items", d
|
@uninstall()
|
||||||
, (e, s) ->
|
.then () => @notify __("Packaged uninstalled")
|
||||||
me.error __("Fail to fetch packages list from: {0}", url)
|
.catch (e) => @error e.toString(), e
|
||||||
|
|
||||||
|
@bindKey "CTRL-R", () =>
|
||||||
|
@menuOptionsHandle "repos"
|
||||||
|
|
||||||
|
$(@searchbox).keyup (e) => @search e
|
||||||
|
|
||||||
|
refreshRepoList: () ->
|
||||||
|
list = (v for v in @systemsetting.system.repositories)
|
||||||
|
list.unshift {
|
||||||
|
text: "Installed"
|
||||||
|
}
|
||||||
|
@repo.set "data", list
|
||||||
|
|
||||||
|
search: (e) ->
|
||||||
|
switch e.which
|
||||||
|
when 37
|
||||||
|
e.preventDefault()
|
||||||
|
when 38
|
||||||
|
@applist.selectPrev()
|
||||||
|
e.preventDefault()
|
||||||
|
when 39
|
||||||
|
e.preventDefault()
|
||||||
|
when 40
|
||||||
|
@applist.selectNext()
|
||||||
|
e.preventDefault()
|
||||||
|
when 13
|
||||||
|
e.preventDefault()
|
||||||
|
else
|
||||||
|
text = @searchbox.value
|
||||||
|
@applist.set "data", (v for v in @apps_meta) if text.length is 2
|
||||||
|
return if text.length < 3
|
||||||
|
result = []
|
||||||
|
term = new RegExp text, 'i'
|
||||||
|
result.push v for v in @apps_meta when v.text.match term
|
||||||
|
@applist.set "data", result
|
||||||
|
|
||||||
|
|
||||||
|
fetchApps: (data) ->
|
||||||
|
if not data.url
|
||||||
|
pkgcache = @systemsetting.system.packages
|
||||||
|
list = []
|
||||||
|
for k, v of pkgcache
|
||||||
|
list.push {
|
||||||
|
className: v.app,
|
||||||
|
name: v.name,
|
||||||
|
text: v.name,
|
||||||
|
icon: v.icon,
|
||||||
|
iconclass: v.iconclass,
|
||||||
|
category: v.category,
|
||||||
|
author: v.info.author,
|
||||||
|
version: v.version,
|
||||||
|
description: "#{v.path}/REAME.md"
|
||||||
|
}
|
||||||
|
@apps_meta = list
|
||||||
|
@applist.set "data", list
|
||||||
|
return
|
||||||
|
|
||||||
|
@_api.get data.url
|
||||||
|
.then ( d ) =>
|
||||||
|
for v in d
|
||||||
|
v.text = v.name
|
||||||
|
v.iconclass = "fa fa-adn"
|
||||||
|
@apps_meta = d
|
||||||
|
@applist.set "data", d
|
||||||
|
.catch (e) ->
|
||||||
|
@error __("Fail to fetch packages list from: {0}", data.url), e
|
||||||
|
|
||||||
appDetail: (d) ->
|
appDetail: (d) ->
|
||||||
me = @
|
|
||||||
($ @container).css "visibility", "visible"
|
($ @container).css "visibility", "visible"
|
||||||
( $ @appname ).html d.name
|
( $ @appname ).html d.name
|
||||||
(@find "vstat").set "text", ""
|
(@find "vstat").set "text", ""
|
||||||
if d.description
|
if d.description
|
||||||
d.description.asFileHandler().read (text) ->
|
d.description.asFileHandle().read().then (text) =>
|
||||||
converter = new showdown.Converter()
|
converter = new showdown.Converter()
|
||||||
($ me.appdesc).html converter.makeHtml text
|
($ @appdesc).html(converter.makeHtml text)
|
||||||
|
.catch (e) => @notify __("Unable to read package description")
|
||||||
else
|
else
|
||||||
($ me.appdesc).empty()
|
($ @appdesc).empty()
|
||||||
pkgcache = @systemsetting.system.packages
|
pkgcache = @systemsetting.system.packages
|
||||||
@btinstall.set "text", "__(Install)"
|
@btinstall.set "text", "__(Install)"
|
||||||
@btinstall.set "dirty", false
|
@btinstall.set "dirty", false
|
||||||
@ -89,7 +157,8 @@ class MarketPlace extends this.OS.GUI.BaseApplication
|
|||||||
@btinstall.set "dirty", true
|
@btinstall.set "dirty", true
|
||||||
@btinstall.set "text", "__(Update)"
|
@btinstall.set "text", "__(Update)"
|
||||||
($ @btinstall).show()
|
($ @btinstall).show()
|
||||||
(@find "vstat").set "text", __("Your application version is older ({0} < {1})", vs, ovs)
|
(@find "vstat").set "text",
|
||||||
|
__("Your application version is older ({0} < {1})", vs, ovs)
|
||||||
($ @btremove).show()
|
($ @btremove).show()
|
||||||
($ @btexec).show()
|
($ @btexec).show()
|
||||||
else
|
else
|
||||||
@ -98,111 +167,185 @@ class MarketPlace extends this.OS.GUI.BaseApplication
|
|||||||
($ @btexec).hide()
|
($ @btexec).hide()
|
||||||
|
|
||||||
($ @appdetail).empty()
|
($ @appdetail).empty()
|
||||||
for k, v of d when k isnt "name" and k isnt "description"
|
for k, v of d when k isnt "name" and k isnt "description" and k isnt "domel"
|
||||||
($ @appdetail).append $("<li>").append(($ "<span class= 'info-header'>").html k).append $("<span>").html v
|
($ @appdetail).append(
|
||||||
|
$("<li>")
|
||||||
|
.append(($ "<span class= 'info-header'>").html k)
|
||||||
|
.append $("<span>").html v
|
||||||
|
)
|
||||||
|
|
||||||
menu: () ->
|
menu: () ->
|
||||||
me = @
|
|
||||||
return [
|
return [
|
||||||
{ text: "__(Options)", child: [
|
{
|
||||||
{ text: "__(Repositories)", shortcut: "C-R" }
|
text: "__(Options)", child: [
|
||||||
] , onmenuselect: (e) ->
|
{ text: "__(Repositories)", shortcut: "C-R", id: "repos" },
|
||||||
me.openDialog new RepositoryDialog()
|
{ text: "__(Install from zip)", shortcut: "C-I", id: "install" }
|
||||||
|
] , onchildselect: (e) =>
|
||||||
|
@menuOptionsHandle e.data.item.get("data").id
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
install: (f) ->
|
menuOptionsHandle: (id) ->
|
||||||
me = @
|
switch id
|
||||||
app = @applist.get "selected"
|
when "repos"
|
||||||
|
@openDialog new RepositoryDialog(), {
|
||||||
|
title: __("Repositories"),
|
||||||
|
data: @systemsetting.system.repositories
|
||||||
|
}
|
||||||
|
when "install"
|
||||||
|
@localInstall().then () =>
|
||||||
|
@notify __("Package installed")
|
||||||
|
.catch (e) => @error __("Unable to install package"), e
|
||||||
|
else
|
||||||
|
|
||||||
|
remoteInstall: () ->
|
||||||
|
el = @applist.get "selectedItem"
|
||||||
|
return unless el
|
||||||
|
app = el.get "data"
|
||||||
return unless app
|
return unless app
|
||||||
# get blob file
|
# get blob file
|
||||||
@_api.blob app.download, (data) ->
|
new Promise (resolve, reject) =>
|
||||||
JSZip.loadAsync(data).then (zip) ->
|
@_api.blob app.download
|
||||||
pth = "#{me.installdir}/#{app.className}"
|
.then (data) =>
|
||||||
dir = [pth]
|
@install data, app
|
||||||
files = []
|
.then () -> resolve()
|
||||||
for name, file of zip.files
|
.catch (e) -> reject(e)
|
||||||
if file.dir
|
.catch (e) -> reject e
|
||||||
dir.push(pth + "/" + name)
|
|
||||||
else
|
localInstall: () ->
|
||||||
files.push name
|
new Promise (resolve, reject) =>
|
||||||
idx = files.indexOf "package.json"
|
@openDialog("FileDialog", {
|
||||||
return me.error __("Invalid package: Meta data file not found") if idx < 0
|
title: "__(Select package archive)",
|
||||||
# create all directory
|
mimes: [".*/zip"]
|
||||||
me.mkdirs app.className, dir, () ->
|
}).then (d) =>
|
||||||
me.installFile app.className, zip, files, () ->
|
d.file.path.asFileHandle().read("binary").then (data) =>
|
||||||
zip.file("package.json").async("string").then (d) ->
|
@install data
|
||||||
v = JSON.parse d
|
.then (n) =>
|
||||||
|
@repo.unselect()
|
||||||
|
@repo.set "selected", 0
|
||||||
|
apps = (v.className for v in @applist.get("data"))
|
||||||
|
idx = apps.indexOf n
|
||||||
|
if idx >= 0
|
||||||
|
@applist.set "selected", idx
|
||||||
|
resolve()
|
||||||
|
.catch (e) -> reject(e)
|
||||||
|
.catch (e) -> reject e
|
||||||
|
.catch (e) -> reject e
|
||||||
|
|
||||||
|
install: (data, meta) ->
|
||||||
|
new Promise (resolve, reject) =>
|
||||||
|
JSZip.loadAsync(data).then (zip) =>
|
||||||
|
zip.file("package.json").async("string").then (d) =>
|
||||||
|
v = JSON.parse d
|
||||||
|
pth = "#{@installdir}/#{v.app}"
|
||||||
|
dir = [pth]
|
||||||
|
files = []
|
||||||
|
for name, file of zip.files
|
||||||
|
if file.dir
|
||||||
|
dir.push(pth + "/" + name)
|
||||||
|
else
|
||||||
|
files.push name
|
||||||
|
# create all directory
|
||||||
|
@mkdirs(dir).then () =>
|
||||||
|
@installFile(v.app, zip, files).then () =>
|
||||||
|
app_meta = {
|
||||||
|
className: v.app,
|
||||||
|
name: v.name,
|
||||||
|
text: v.name,
|
||||||
|
icon: v.icon,
|
||||||
|
iconclass: v.iconclass,
|
||||||
|
category: v.category,
|
||||||
|
author: v.info.author,
|
||||||
|
version: v.version,
|
||||||
|
description: if meta then meta.description else undefined,
|
||||||
|
download: if meta then meta.download else undefined
|
||||||
|
}
|
||||||
v.text = v.name
|
v.text = v.name
|
||||||
v.filename = app.className
|
v.filename = v.app
|
||||||
v.type = "app"
|
v.type = "app"
|
||||||
v.mime = "antos/app"
|
v.mime = "antos/app"
|
||||||
v.iconclass = "fa fa-adn" unless v.iconclass or v.icon
|
v.iconclass = "fa fa-adn" unless v.iconclass or v.icon
|
||||||
v.path = pth
|
v.path = pth
|
||||||
me.systemsetting.system.packages[app.className] = v
|
@systemsetting.system.packages[v.app] = v
|
||||||
me.notify __("Application installed")
|
@notify __("Application installed")
|
||||||
me._gui.refreshSystemMenu()
|
@appDetail app_meta
|
||||||
me.appDetail app
|
resolve(v.name)
|
||||||
.catch (err) ->
|
.catch (e) -> reject e
|
||||||
me.error __("Error reading package meta data: {0}", err)
|
.catch (e) -> reject e
|
||||||
|
.catch (err) -> reject err
|
||||||
|
.catch (e) -> reject e
|
||||||
|
|
||||||
, (err, s) ->
|
uninstall: () ->
|
||||||
return me.error __("Cannot down load the app {0}", err) if err
|
new Promise (resolve, reject) =>
|
||||||
uninstall: (f) ->
|
el = @applist.get "selectedItem"
|
||||||
me = @
|
return unless el
|
||||||
sel = @applist.get "selected"
|
sel = el.get "data"
|
||||||
name = sel.className
|
return unless sel
|
||||||
return unless sel
|
name = sel.className
|
||||||
app = @systemsetting.system.packages[sel.className]
|
app = @systemsetting.system.packages[sel.className]
|
||||||
return unless app
|
return unless app
|
||||||
@openDialog "YesNoDialog",
|
@openDialog("YesNoDialog", {
|
||||||
(d) ->
|
title: __("Uninstall") ,
|
||||||
|
text: __("Uninstall: {0}?", app.name)
|
||||||
|
}).then (d) =>
|
||||||
return unless d
|
return unless d
|
||||||
app.path.asFileHandler().remove (r) ->
|
app.path.asFileHandle().remove().then (r) =>
|
||||||
return me.error __("Cannot uninstall package: {0}", r.error) if r.error
|
if r.error
|
||||||
me.notify __("Package uninstalled")
|
return reject @_api.throwe __("Cannot uninstall package: {0}", r.error)
|
||||||
delete me.systemsetting.system.packages[name]
|
@notify __("Package uninstalled")
|
||||||
me._gui.unloadApp name
|
delete @systemsetting.system.packages[name]
|
||||||
me._gui.refreshSystemMenu()
|
@_gui.unloadApp name
|
||||||
me.appDetail sel
|
if sel.download
|
||||||
f() if f
|
@appDetail sel
|
||||||
, __("Uninstall") ,
|
else
|
||||||
{ text: __("Uninstall: {0}?", app.name) }
|
@applist.remove el
|
||||||
|
($ @container).css "visibility", "hidden"
|
||||||
|
resolve()
|
||||||
|
.catch (e) -> reject e
|
||||||
|
.catch (e) -> reject e
|
||||||
|
|
||||||
update: () ->
|
update: () ->
|
||||||
me = @
|
new Promise (resolve, reject) =>
|
||||||
new Promise (r, e) ->
|
@uninstall().then () =>
|
||||||
me.uninstall () ->
|
@remoteInstall()
|
||||||
r()
|
.then () -> resolve()
|
||||||
.then () ->
|
.catch (e) -> reject e
|
||||||
me.install()
|
.catch (e) -> reject e
|
||||||
|
|
||||||
mkdirs: (n, list, f) ->
|
mkdirs: (list) ->
|
||||||
me = @
|
new Promise (resolve, reject) =>
|
||||||
if list.length is 0
|
return resolve() if list.length is 0
|
||||||
f() if f
|
dir = (list.splice 0, 1)[0].asFileHandle()
|
||||||
return
|
path = dir.parent()
|
||||||
dir = (list.splice 0, 1)[0].asFileHandler()
|
dname = dir.basename
|
||||||
path = dir.parent()
|
path.asFileHandle().mk dname
|
||||||
dname = dir.basename
|
.then (r) =>
|
||||||
path.asFileHandler().mk dname, (r) ->
|
return reject(@_api.throwe __("Cannot create {0}", "#{path}/#{dir}")) if r.error
|
||||||
return me.mkdirs n, list, f if r.result
|
@mkdirs list
|
||||||
me.error __("Cannot create {0}", "#{path}/#{dir}")
|
.then () -> resolve()
|
||||||
|
.catch (e) -> reject e
|
||||||
|
.catch (e) -> reject e
|
||||||
|
|
||||||
installFile: (n, zip, files, f) ->
|
installFile: (n, zip, files) ->
|
||||||
me = @
|
new Promise (resolve, reject) =>
|
||||||
if files.length is 0
|
return resolve() if files.length is 0
|
||||||
f() if f
|
file = (files.splice 0, 1)[0]
|
||||||
return
|
path = "#{@installdir}/#{n}/#{file}"
|
||||||
file = (files.splice 0, 1)[0]
|
zip.file(file).async("uint8array").then (d) =>
|
||||||
path = "#{me.installdir}/#{n}/#{file}"
|
fp = path.asFileHandle()
|
||||||
zip.file(file).async("uint8array").then (d) ->
|
fp.cache = new Blob [d], { type: "octet/stream" }
|
||||||
fp = path.asFileHandler()
|
fp.write "text/plain"
|
||||||
fp.cache = new Blob [d], { type: "octet/stream" }
|
.then (r) =>
|
||||||
fp.write "text/plain", (r) ->
|
return reject @_api.throwe(__("Cannot install {0}", path)) if r.error
|
||||||
return me.installFile n, zip, files, f if r.result
|
@installFile n, zip, files
|
||||||
me.error __("Cannot install {0}", path)
|
.then () -> resolve()
|
||||||
|
.catch (e) -> reject()
|
||||||
|
.catch (e) -> reject e
|
||||||
|
.catch (e) -> reject e
|
||||||
|
|
||||||
MarketPlace.dependencies = [ "jszip.min", "showdown.min" ]
|
MarketPlace.dependencies = [
|
||||||
|
"os://scripts/jszip.min.js",
|
||||||
|
"os://scripts/showdown.min.js"
|
||||||
|
]
|
||||||
MarketPlace.singleton = true
|
MarketPlace.singleton = true
|
||||||
this.OS.register "MarketPlace", MarketPlace
|
this.OS.register "MarketPlace", MarketPlace
|
@ -1,17 +1,9 @@
|
|||||||
afx-app-window[data-id ='marketplace-win'] afx-resizer{
|
|
||||||
background-color: transparent;
|
|
||||||
border-left: 1px solid #cbcbcb;
|
|
||||||
}
|
|
||||||
afx-app-window[data-id ='marketplace-win'] afx-list-view[data-id='applist']{
|
|
||||||
background-color: #f6F6F6;
|
|
||||||
padding:0;
|
|
||||||
}
|
|
||||||
afx-app-window[data-id="marketplace-win"] afx-list-view[data-id='repo'] div.list-container{
|
afx-app-window[data-id="marketplace-win"] afx-list-view[data-id='repo'] div.list-container{
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
afx-app-window[data-id="marketplace-win"] afx-vbox[data-id='container'] {
|
afx-app-window[data-id="marketplace-win"] afx-vbox[data-id='container'] {
|
||||||
color: #414339;
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
afx-app-window[data-id="marketplace-win"] afx-vbox[data-id='container'] afx-hbox {
|
afx-app-window[data-id="marketplace-win"] afx-vbox[data-id='container'] afx-hbox {
|
||||||
@ -21,7 +13,6 @@ afx-app-window[data-id="marketplace-win"] div[data-id='appname'] {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
color: #414339;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afx-app-window[data-id="marketplace-win"] div[data-id='appname']:before {
|
afx-app-window[data-id="marketplace-win"] div[data-id='appname']:before {
|
||||||
@ -30,7 +21,6 @@ afx-app-window[data-id="marketplace-win"] div[data-id='appname']:before {
|
|||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
color: #414339;
|
|
||||||
}
|
}
|
||||||
afx-app-window[data-id="marketplace-win"] p[data-id='app-desc'] {
|
afx-app-window[data-id="marketplace-win"] p[data-id='app-desc'] {
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
@ -47,6 +37,23 @@ afx-app-window[data-id="marketplace-win"] ul[data-id='app-detail'] {
|
|||||||
display: table;
|
display: table;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
afx-app-window[data-id="marketplace-win"] afx-hbox[data-id="search-container"] {
|
||||||
|
border-bottom: 1px solid #afafaf;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id="marketplace-win"] afx-hbox[data-id="search-container"] input{
|
||||||
|
border: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id="marketplace-win"] div[data-id="searchicon"]:before{
|
||||||
|
content: "\f002";
|
||||||
|
display: block;
|
||||||
|
background-color:transparent;
|
||||||
|
color:#afafaf;
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
padding-top: 3px;
|
||||||
|
padding-left:3px;
|
||||||
|
/* font-size: 25px; */
|
||||||
|
}
|
||||||
afx-app-window[data-id="marketplace-win"] ul[data-id='app-detail'] li{
|
afx-app-window[data-id="marketplace-win"] ul[data-id='app-detail'] li{
|
||||||
padding:0;
|
padding:0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"app":"MarketPlace",
|
"app":"MarketPlace",
|
||||||
"name":"Application store",
|
"name":"Application store",
|
||||||
"description":"Application store and repository management",
|
"description":"Application store",
|
||||||
"info":{
|
"info":{
|
||||||
"author": "Xuan Sang LE",
|
"author": "Xuan Sang LE",
|
||||||
"email": "xsang.le@gmail.com"
|
"email": "xsang.le@gmail.com"
|
||||||
@ -9,5 +9,6 @@
|
|||||||
"version":"0.0.1-a",
|
"version":"0.0.1-a",
|
||||||
"category":"System",
|
"category":"System",
|
||||||
"iconclass":"fa fa-adn",
|
"iconclass":"fa fa-adn",
|
||||||
"mimes":["none"]
|
"mimes":["none"],
|
||||||
|
"locales": {}
|
||||||
}
|
}
|
@ -1,13 +1,17 @@
|
|||||||
<afx-app-window data-id = "marketplace-win" apptitle="MarketPlace" width="500" height="400">
|
<afx-app-window data-id = "marketplace-win" apptitle="MarketPlace" width="500" height="400">
|
||||||
<afx-hbox >
|
<afx-hbox >
|
||||||
<afx-vbox data-width = "172" data-id = "sidebar" min-width="172">
|
<afx-vbox data-width = "172" data-id = "sidebar" min-width="172">
|
||||||
<afx-list-view data-id = "repo" dropdown = "true" data-height= "30" width = "150"></afx-list-view>
|
<afx-list-view data-id = "repo" dropdown = "true" data-height= "25" width = "150"></afx-list-view>
|
||||||
|
<afx-hbox data-height= "23" data-id="search-container">
|
||||||
|
<div data-width="17" data-id="searchicon"></div>
|
||||||
|
<input data-id = "searchbox" />
|
||||||
|
</afx-hbox>
|
||||||
<afx-list-view data-id = "applist" dropdown = "false" width = "150"></afx-list-view>
|
<afx-list-view data-id = "applist" dropdown = "false" width = "150"></afx-list-view>
|
||||||
</afx-vbox>
|
</afx-vbox>
|
||||||
<afx-resizer data-width = "3" ></afx-resizer>
|
<afx-resizer data-width = "3" ></afx-resizer>
|
||||||
<afx-vbox data-id = "container">
|
<afx-vbox data-id = "container">
|
||||||
<div data-id = "appname" data-height = "25"></div>
|
<div data-id = "appname" data-height = "25"></div>
|
||||||
<afx-hbox data-height = "grow">
|
<afx-hbox data-height = "30">
|
||||||
<div style = "text-align:left;">
|
<div style = "text-align:left;">
|
||||||
<afx-button data-id = "bt-remove" text = "__(Uninstall)"></afx-button>
|
<afx-button data-id = "bt-remove" text = "__(Uninstall)"></afx-button>
|
||||||
<afx-button data-id = "bt-exec" text = "__(Launch)"></afx-button>
|
<afx-button data-id = "bt-exec" text = "__(Launch)"></afx-button>
|
||||||
|
@ -102,14 +102,12 @@ afx-file-view afx-tree-view .afx-tree-view-item:before{
|
|||||||
content: "\f016";
|
content: "\f016";
|
||||||
font-family: "FontAwesome";
|
font-family: "FontAwesome";
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #414339;
|
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
afx-file-view afx-tree-view div.afx_tree_item_selected, afx-file-view afx-tree-view div.afx_tree_item_selected:hover{
|
afx-file-view afx-tree-view div.afx_tree_item_selected, afx-file-view afx-tree-view div.afx_tree_item_selected:hover{
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color:#414339;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afx-file-view afx-tree-view li.itemname{
|
afx-file-view afx-tree-view li.itemname{
|
||||||
|
@ -29,7 +29,7 @@ afx-list-view > div.list-container > ul > afx-list-item > li.selected{
|
|||||||
}
|
}
|
||||||
|
|
||||||
afx-list-view.dropdown > div.list-container > ul{
|
afx-list-view.dropdown > div.list-container > ul{
|
||||||
border:1px solid #a6a6a6;
|
border:1px solid #262626;
|
||||||
box-shadow: 0px 3px 6px 0px rgba(0,0,0,0.65);
|
box-shadow: 0px 3px 6px 0px rgba(0,0,0,0.65);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
max-height: 150px;
|
max-height: 150px;
|
||||||
@ -42,7 +42,7 @@ afx-list-view.dropdown div.list-container div{
|
|||||||
color: white;
|
color: white;
|
||||||
padding-top:3px;
|
padding-top:3px;
|
||||||
padding-bottom: 3px;
|
padding-bottom: 3px;
|
||||||
border:1px solid #a6a6a6;
|
border:1px solid #262626;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
height: 17px;
|
height: 17px;
|
||||||
@ -55,14 +55,12 @@ afx-list-view.dropdown div.list-container div:before {
|
|||||||
font-family: "FontAwesome";
|
font-family: "FontAwesome";
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
color: #414339;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top:25%;
|
top:25%;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
}
|
}
|
||||||
afx-list-view.dropdown > div.list-container > ul li:hover{
|
afx-list-view.dropdown > div.list-container > ul li:hover{
|
||||||
background-color: #dcdcdc;
|
background-color: #464646;
|
||||||
color: #414339;
|
|
||||||
}
|
}
|
||||||
afx-list-view ul.complex-content{
|
afx-list-view ul.complex-content{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
afx-resizer {
|
afx-resizer {
|
||||||
background-color: #868686;
|
background-color: transparent;
|
||||||
|
border-left: 1px solid #262626;
|
||||||
}
|
}
|
@ -101,14 +101,12 @@ afx-file-view afx-tree-view .afx-tree-view-item:before{
|
|||||||
content: "\f016";
|
content: "\f016";
|
||||||
font-family: "FontAwesome";
|
font-family: "FontAwesome";
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #414339;
|
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
afx-file-view afx-tree-view div.afx_tree_item_selected, afx-file-view afx-tree-view div.afx_tree_item_selected:hover{
|
afx-file-view afx-tree-view div.afx_tree_item_selected, afx-file-view afx-tree-view div.afx_tree_item_selected:hover{
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color:#414339;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
afx-file-view afx-tree-view li.itemname{
|
afx-file-view afx-tree-view li.itemname{
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
afx-resizer {
|
afx-resizer {
|
||||||
background-color: #cbcbcb;
|
background-color: transparent;
|
||||||
|
border-left: 1px solid #868686;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user