mirror of
https://github.com/antos-rde/antosdk-apps.git
synced 2024-12-25 11:48:21 +01:00
add archive manager
This commit is contained in:
parent
232465f8ed
commit
d20db3e0fb
13
Archive/README.md
Normal file
13
Archive/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Archive
|
||||||
|
|
||||||
|
Small application for zip file manager
|
||||||
|
|
||||||
|
## Features
|
||||||
|
* Open, create zip file Archive
|
||||||
|
* Add/remove file/folder to archive
|
||||||
|
* Extract zip file content
|
||||||
|
|
||||||
|
## Changle log
|
||||||
|
|
||||||
|
### v0.0.1-a
|
||||||
|
* First release
|
17
Archive/assets/scheme.html
Normal file
17
Archive/assets/scheme.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<afx-app-window apptitle="Archive" width="250" height="300" data-id="Archive">
|
||||||
|
<afx-vbox>
|
||||||
|
<afx-tree-view data-id="filetree"></afx-tree-view>
|
||||||
|
<div data-height="5"></div>
|
||||||
|
<afx-hbox data-height="30">
|
||||||
|
<div data-width="10"></div>
|
||||||
|
<div style="text-align: left;">
|
||||||
|
<afx-button iconclass="fa fa-plus-circle" data-id="btaradd"></afx-button>
|
||||||
|
<afx-button iconclass="fa fa-minus-circle" data-id="btardel"></afx-button>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right;">
|
||||||
|
<afx-button text="__(Extract)" data-id="btarxtract"></afx-button>
|
||||||
|
</div>
|
||||||
|
<div data-width="10"></div>
|
||||||
|
</afx-hbox>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-app-window>
|
13
Archive/build/debug/README.md
Normal file
13
Archive/build/debug/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Archive
|
||||||
|
|
||||||
|
Small application for zip file manager
|
||||||
|
|
||||||
|
## Features
|
||||||
|
* Open, create zip file Archive
|
||||||
|
* Add/remove file/folder to archive
|
||||||
|
* Extract zip file content
|
||||||
|
|
||||||
|
## Changle log
|
||||||
|
|
||||||
|
### v0.0.1-a
|
||||||
|
* First release
|
20
Archive/build/debug/main.css
Normal file
20
Archive/build/debug/main.css
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
afx-app-window[data-id="Archive"] afx-tree-view .afx-tree-view-folder-close:before{
|
||||||
|
content: "\f07b";
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
color:#76D2F9;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id="Archive"] afx-tree-view .afx-tree-view-folder-open:before{
|
||||||
|
content: "\f07c";
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
color:#76D2F9;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id="Archive"] afx-tree-view .afx-tree-view-item:before{
|
||||||
|
content: "\f016";
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
1
Archive/build/debug/main.js
Normal file
1
Archive/build/debug/main.js
Normal file
File diff suppressed because one or more lines are too long
15
Archive/build/debug/package.json
Normal file
15
Archive/build/debug/package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"app":"Archive",
|
||||||
|
"name":"Archive",
|
||||||
|
"pkgname": "Archive",
|
||||||
|
"description":"Create of extract zip archive",
|
||||||
|
"info":{
|
||||||
|
"author": "Xuan Sang LE",
|
||||||
|
"email": "mrsang@lxsang.me"
|
||||||
|
},
|
||||||
|
"version":"0.0.1-a",
|
||||||
|
"category":"Other",
|
||||||
|
"iconclass":"fa fa-archive",
|
||||||
|
"mimes":["application/zip"],
|
||||||
|
"locale": {}
|
||||||
|
}
|
17
Archive/build/debug/scheme.html
Normal file
17
Archive/build/debug/scheme.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<afx-app-window apptitle="Archive" width="250" height="300" data-id="Archive">
|
||||||
|
<afx-vbox>
|
||||||
|
<afx-tree-view data-id="filetree"></afx-tree-view>
|
||||||
|
<div data-height="5"></div>
|
||||||
|
<afx-hbox data-height="30">
|
||||||
|
<div data-width="10"></div>
|
||||||
|
<div style="text-align: left;">
|
||||||
|
<afx-button iconclass="fa fa-plus-circle" data-id="btaradd"></afx-button>
|
||||||
|
<afx-button iconclass="fa fa-minus-circle" data-id="btardel"></afx-button>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right;">
|
||||||
|
<afx-button text="__(Extract)" data-id="btarxtract"></afx-button>
|
||||||
|
</div>
|
||||||
|
<div data-width="10"></div>
|
||||||
|
</afx-hbox>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-app-window>
|
BIN
Archive/build/release/Archive.zip
Normal file
BIN
Archive/build/release/Archive.zip
Normal file
Binary file not shown.
275
Archive/coffees/main.coffee
Normal file
275
Archive/coffees/main.coffee
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
class Archive extends this.OS.application.BaseApplication
|
||||||
|
constructor: ( args ) ->
|
||||||
|
super "Archive", args
|
||||||
|
@currfile = "Untitled".asFileHandle()
|
||||||
|
if @args and @args.length > 0 and @args[0].path
|
||||||
|
@currfile = args[0].path.asFileHandle()
|
||||||
|
|
||||||
|
main: () ->
|
||||||
|
@btadd = @find "btaradd"
|
||||||
|
@btdel = @find "btardel"
|
||||||
|
@btxtract = @find "btarxtract"
|
||||||
|
@filetree = @find "filetree"
|
||||||
|
@zip = undefined
|
||||||
|
@bindKey "ALT-N", () => @fileMenuHandle "new"
|
||||||
|
@bindKey "ALT-O", () => @fileMenuHandle "open"
|
||||||
|
@bindKey "CTRL-S", () => @fileMenuHandle "save"
|
||||||
|
@bindKey "ALT-S", () => @fileMenuHandle "saveas"
|
||||||
|
|
||||||
|
@btxtract.onbtclick = (e) =>
|
||||||
|
item = @filetree.selectedItem
|
||||||
|
return @notify __("Please select file/folder to extract") unless item
|
||||||
|
treedata = item.data
|
||||||
|
@openDialog "FileDialog", { title: __("Select a folder"), mimes: ["dir"] }
|
||||||
|
.then (d) =>
|
||||||
|
@xtract(treedata, d.file.path)
|
||||||
|
.then () => @notify __("extract successful: {0}", treedata.path)
|
||||||
|
.catch (e) => @error e.toString(), e
|
||||||
|
.catch (e) => @error e.toString(), e
|
||||||
|
|
||||||
|
|
||||||
|
@btadd.onbtclick = (e) => @actionAdd()
|
||||||
|
|
||||||
|
@btdel.onbtclick = (e) => @actionDel()
|
||||||
|
|
||||||
|
@filetree.contextmenuHandle = (e, m) =>
|
||||||
|
item = @filetree.selectedItem
|
||||||
|
return unless item
|
||||||
|
mdata = [
|
||||||
|
{ text: "__(Delete)", onmenuselect: () => @actionDel()},
|
||||||
|
{ text: "__(Info)", onmenuselect: () => @actionInfo()}
|
||||||
|
]
|
||||||
|
if item.data.type is "dir"
|
||||||
|
mdata.unshift { text: "__(Add)", onmenuselect: () => @actionAdd() }
|
||||||
|
|
||||||
|
|
||||||
|
m.items = mdata
|
||||||
|
m.show(e)
|
||||||
|
|
||||||
|
@openar(@currfile)
|
||||||
|
|
||||||
|
actionAdd: () ->
|
||||||
|
item = @filetree.selectedItem
|
||||||
|
return @notify __("Please select a destination folder") unless item and item.data.type is "dir"
|
||||||
|
treedata = item.data
|
||||||
|
@openDialog "FileDialog", { title: __("Select a file/folder") }
|
||||||
|
.then (d) =>
|
||||||
|
@addToZip d.file, "#{treedata.path}/#{d.file.path.asFileHandle().basename}"
|
||||||
|
.then () =>
|
||||||
|
@currfile.dirty = true
|
||||||
|
@refreshTreeFile()
|
||||||
|
.catch (e) => @error e.toString(), e
|
||||||
|
.catch (e) => @error e.toString(), e
|
||||||
|
|
||||||
|
actionDel: () ->
|
||||||
|
item = @filetree.selectedItem
|
||||||
|
return @notify __("Please select a destination folder") unless item
|
||||||
|
treedata = item.data
|
||||||
|
return @notify __("You cannot delete the root node") if treedata.root
|
||||||
|
|
||||||
|
@ask {title: "__(Delete)", text: __("Do you really want to delete: {0}?", treedata.text) }
|
||||||
|
.then (d) =>
|
||||||
|
return unless d
|
||||||
|
@zip.remove(treedata.path.trimBy("/"))
|
||||||
|
@currfile.dirty = true
|
||||||
|
@refreshTreeFile()
|
||||||
|
.catch (e) => @error e.toString(), e
|
||||||
|
|
||||||
|
actionInfo: () ->
|
||||||
|
item = @filetree.selectedItem
|
||||||
|
return @notify __("Please select a file/folder") unless item
|
||||||
|
key = item.data.path.trimBy("/")
|
||||||
|
key = "#{key}/" if item.data.type is "dir"
|
||||||
|
meta = @zip.files[key]
|
||||||
|
return @notify __("Cannot get entry meta data") unless meta
|
||||||
|
@openDialog "InfoDialog", {
|
||||||
|
title: "About: #{meta.name}",
|
||||||
|
name: meta.name,
|
||||||
|
date: meta.date,
|
||||||
|
dir: meta.dir,
|
||||||
|
dataBinary: meta._dataBinary,
|
||||||
|
size: meta._data.uncompressedSize
|
||||||
|
}
|
||||||
|
|
||||||
|
openar: (file) ->
|
||||||
|
@zip = undefined
|
||||||
|
if file.filename is "Untitled"
|
||||||
|
@zip = new JSZip()
|
||||||
|
@currfile = file
|
||||||
|
@refreshTreeFile()
|
||||||
|
else
|
||||||
|
# open the file and refresh filetree
|
||||||
|
file.read("binary")
|
||||||
|
.then (data) =>
|
||||||
|
JSZip.loadAsync(data)
|
||||||
|
.then (zip) =>
|
||||||
|
@zip = zip
|
||||||
|
@currfile = file
|
||||||
|
@refreshTreeFile()
|
||||||
|
.catch (e) =>
|
||||||
|
@error __("Wrong zip format: {0}", e.toString()), e
|
||||||
|
.catch (e) =>
|
||||||
|
@error __("Unable to read archive: {0}", file.path), e
|
||||||
|
|
||||||
|
refreshTreeFile: () ->
|
||||||
|
return unless @zip
|
||||||
|
treedata = {
|
||||||
|
text: @currfile.filename.trimRight(".zip"),
|
||||||
|
type: "dir"
|
||||||
|
path: "",
|
||||||
|
open: true,
|
||||||
|
root: true,
|
||||||
|
nodes: []
|
||||||
|
}
|
||||||
|
|
||||||
|
for k,v of @zip.files
|
||||||
|
leaf = @putFileInTree k.split("/"), treedata
|
||||||
|
if not v.dir
|
||||||
|
leaf.type = "file"
|
||||||
|
delete leaf.nodes
|
||||||
|
@filetree.data = treedata
|
||||||
|
|
||||||
|
putFileInTree: (patharr, treedata) ->
|
||||||
|
names = (v.text for v in treedata.nodes)
|
||||||
|
rep = patharr.shift()
|
||||||
|
return treedata unless rep
|
||||||
|
if names.includes rep
|
||||||
|
@putFileInTree patharr, treedata.nodes[names.indexOf rep]
|
||||||
|
else
|
||||||
|
subtree = {
|
||||||
|
text: rep,
|
||||||
|
path: "#{treedata.path}/#{rep}",
|
||||||
|
type: "dir",
|
||||||
|
nodes: []
|
||||||
|
}
|
||||||
|
treedata.nodes.push subtree
|
||||||
|
return @putFileInTree patharr, subtree
|
||||||
|
|
||||||
|
|
||||||
|
xtract: (treedata, to) ->
|
||||||
|
new Promise (resolve, reject) =>
|
||||||
|
if treedata.type is "file"
|
||||||
|
@zip.file(treedata.path.trimBy("/"))
|
||||||
|
.async("uint8array")
|
||||||
|
.then (data) =>
|
||||||
|
fp = "#{to}/#{treedata.text}".asFileHandle()
|
||||||
|
fp.cache = new Blob([data], { type: "octet/stream" })
|
||||||
|
fp.write()
|
||||||
|
.then () -> resolve()
|
||||||
|
.catch (e) -> reject __e e
|
||||||
|
.catch (e) -> reject __e e
|
||||||
|
else
|
||||||
|
#make the dir before extract
|
||||||
|
to.asFileHandle().mk treedata.text
|
||||||
|
.then () =>
|
||||||
|
nodes = (v for v in treedata.nodes)
|
||||||
|
@xtractall nodes, "#{to}/#{treedata.text}"
|
||||||
|
.then -> resolve()
|
||||||
|
.catch (e) -> reject __e e
|
||||||
|
.catch (e) -> reject __e e
|
||||||
|
|
||||||
|
xtractall: (list, to) ->
|
||||||
|
new Promise (resolve, reject) =>
|
||||||
|
return resolve() if list.length is 0
|
||||||
|
el = list.shift()
|
||||||
|
@xtract el, to
|
||||||
|
.then () =>
|
||||||
|
@xtractall list, to
|
||||||
|
.then () -> resolve()
|
||||||
|
.catch (e) -> reject __e e
|
||||||
|
.catch (e) -> reject __e e
|
||||||
|
|
||||||
|
addToZip: (file, to) ->
|
||||||
|
new Promise (resolve, reject) =>
|
||||||
|
if file.type is "dir"
|
||||||
|
file.path.asFileHandle().read().then (data) =>
|
||||||
|
return reject __e @throwe data.error if data.error
|
||||||
|
@addFilesTozip data.result, to
|
||||||
|
.then () -> resolve()
|
||||||
|
.catch (e) => reject __e e
|
||||||
|
else
|
||||||
|
file.path.asFileHandle()
|
||||||
|
.read("binary")
|
||||||
|
.then (data) =>
|
||||||
|
@zip.file(to.trimBy("/"), data, { binary: true })
|
||||||
|
resolve()
|
||||||
|
.catch (e) -> resolve __e e
|
||||||
|
|
||||||
|
addFilesTozip: (list, to) ->
|
||||||
|
new Promise (resolve, reject) =>
|
||||||
|
return resolve() if list.length is 0
|
||||||
|
el = list.shift()
|
||||||
|
@addToZip el, "#{to}/#{el.path.asFileHandle().basename}"
|
||||||
|
.then () =>
|
||||||
|
@addFilesTozip list, to
|
||||||
|
.then () -> resolve()
|
||||||
|
.catch (e) -> reject __e e
|
||||||
|
.catch (e) -> reject __e e
|
||||||
|
|
||||||
|
saveZipAs: () ->
|
||||||
|
@openDialog("FileDialog", {
|
||||||
|
title: __("Save as"),
|
||||||
|
file: @currfile
|
||||||
|
}).then (f) =>
|
||||||
|
d = f.file.path.asFileHandle()
|
||||||
|
d = d.parent() if f.file.type is "file"
|
||||||
|
@currfile.setPath "#{d.path}/#{f.name}"
|
||||||
|
@write()
|
||||||
|
|
||||||
|
write: () ->
|
||||||
|
return unless @zip and @currfile.path isnt "Untitled"
|
||||||
|
@zip .generateAsync({ type: "base64" })
|
||||||
|
.then (data) =>
|
||||||
|
@currfile
|
||||||
|
.setCache(
|
||||||
|
"data:application/zip;base64," + data
|
||||||
|
)
|
||||||
|
.write("base64")
|
||||||
|
.then () =>
|
||||||
|
@currfile.dirty = false
|
||||||
|
@refreshTreeFile()
|
||||||
|
@notify __("zip file saved in {0}", @currfile.path)
|
||||||
|
.catch (e) => @error __("Unable to save zip file: {0}", @currfile.path)
|
||||||
|
|
||||||
|
fileMenuHandle:(id) ->
|
||||||
|
switch id
|
||||||
|
when "open"
|
||||||
|
@openDialog "FileDialog", { title: __("Select a zip file"), mimes: ["application/zip"] }
|
||||||
|
.then (d) =>
|
||||||
|
@openar(d.file.path.asFileHandle())
|
||||||
|
.catch (e) => @error e.toString(), e
|
||||||
|
when "save"
|
||||||
|
return @write() if @currfile.path isnt "Untitled"
|
||||||
|
@saveZipAs()
|
||||||
|
|
||||||
|
when "saveas"
|
||||||
|
@saveZipAs()
|
||||||
|
|
||||||
|
menu: () ->
|
||||||
|
[
|
||||||
|
{
|
||||||
|
text: "__(File)",
|
||||||
|
nodes: [
|
||||||
|
{ text: "__(New)", id:"new", shortcut: "A-N" },
|
||||||
|
{ text: "__(Open)", id:"open", shortcut: "A-O"},
|
||||||
|
{ text: "__(Save)", id:"save", shortcut: "C-S"},
|
||||||
|
{ text: "__(Save as)", id:"saveas", shortcut: "A-S"}
|
||||||
|
],
|
||||||
|
onchildselect: (e) => @fileMenuHandle e.data.item.data.id
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
cleanup: (e) ->
|
||||||
|
return unless @currfile.dirty
|
||||||
|
e.preventDefault()
|
||||||
|
@ask { title: "__(Quit)", text: "__(Zip file has been modified. Quit without saving?)" }
|
||||||
|
.then (d) =>
|
||||||
|
return unless d
|
||||||
|
@currfile.dirty = false
|
||||||
|
@quit()
|
||||||
|
|
||||||
|
Archive.dependencies = [
|
||||||
|
"os://scripts/jszip.min.js"
|
||||||
|
]
|
||||||
|
|
||||||
|
this.OS.register "Archive", Archive
|
19
Archive/css/main.css
Normal file
19
Archive/css/main.css
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
afx-app-window[data-id="Archive"] afx-tree-view .afx-tree-view-folder-close:before{
|
||||||
|
content: "\f07b";
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
color:#76D2F9;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id="Archive"] afx-tree-view .afx-tree-view-folder-open:before{
|
||||||
|
content: "\f07c";
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
color:#76D2F9;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id="Archive"] afx-tree-view .afx-tree-view-item:before{
|
||||||
|
content: "\f016";
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
15
Archive/package.json
Normal file
15
Archive/package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"app":"Archive",
|
||||||
|
"name":"Archive",
|
||||||
|
"pkgname": "Archive",
|
||||||
|
"description":"Create of extract zip archive",
|
||||||
|
"info":{
|
||||||
|
"author": "Xuan Sang LE",
|
||||||
|
"email": "mrsang@lxsang.me"
|
||||||
|
},
|
||||||
|
"version":"0.0.1-a",
|
||||||
|
"category":"Other",
|
||||||
|
"iconclass":"fa fa-archive",
|
||||||
|
"mimes":["application/zip"],
|
||||||
|
"locale": {}
|
||||||
|
}
|
8
Archive/project.json
Normal file
8
Archive/project.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "Archive",
|
||||||
|
"root": "home://workspace/antosdk-apps/Archive",
|
||||||
|
"css": ["css/main.css"],
|
||||||
|
"javascripts": [],
|
||||||
|
"coffees": ["coffees/main.coffee"],
|
||||||
|
"copies": ["assets/scheme.html", "package.json", "README.md"]
|
||||||
|
}
|
@ -17,6 +17,15 @@
|
|||||||
"version": "0.0.6-a",
|
"version": "0.0.6-a",
|
||||||
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/ActivityMonitor/build/release/ActivityMonitor.zip"
|
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/ActivityMonitor/build/release/ActivityMonitor.zip"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pkgname": "Archive",
|
||||||
|
"name": "Archive",
|
||||||
|
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Archive/README.md",
|
||||||
|
"category": "Other",
|
||||||
|
"author": "Xuan Sang LE",
|
||||||
|
"version": "0.0.1-a",
|
||||||
|
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Archive/build/release/Archive.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pkgname": "Blogger",
|
"pkgname": "Blogger",
|
||||||
"name": "Blogging application",
|
"name": "Blogging application",
|
||||||
|
Loading…
Reference in New Issue
Block a user