VFS for Google Drive, 1st working version

This commit is contained in:
Xuan Sang LE 2018-02-28 15:33:57 +01:00
parent 77336716b5
commit 28ab98b055
9 changed files with 178 additions and 20 deletions

View File

@ -304,6 +304,8 @@ class FileDiaLog extends BaseDialog
(@find "bt-cancel").set "onbtclick", (e) -> (@find "bt-cancel").set "onbtclick", (e) ->
me.quit() me.quit()
($ filename).css("display", "block").val @data.file.basename or "Untitled" if @data and @data.file if @data and @data.file
($ filename).css("display", "block").val @data.file.basename or "Untitled"
@trigger "resize"
this.OS.register "FileDiaLog", FileDiaLog this.OS.register "FileDiaLog", FileDiaLog

View File

@ -103,9 +103,11 @@ self.OS.API =
.done (data) -> .done (data) ->
_API.loaded q, p, "OK" _API.loaded q, p, "OK"
c(data) c(data)
o.remove()
.fail (e, s) -> .fail (e, s) ->
_API.loaded q, p, "FAIL" _API.loaded q, p, "FAIL"
f(e, s) f(e, s)
o.remove()
o.click() o.click()

View File

@ -353,7 +353,7 @@ self.OS.GUI =
_OS.cleanup() _OS.cleanup()
# get setting from conf # get setting from conf
_OS.systemSetting(conf) _OS.systemSetting(conf)
console.log _OS.setting #console.log _OS.setting
# load theme # load theme
_GUI.loadTheme _OS.setting.appearance.theme _GUI.loadTheme _OS.setting.appearance.theme
# initDM # initDM

View File

@ -60,6 +60,16 @@
self.items.unshift(e) self.items.unshift(e)
if(u) self.update() if(u) self.update()
} }
self.root.replaceItem = function(o, n, u)
{
var ix = self.items.indexOf(o)
if(ix >= 0)
{
self.items[ix] = n
if(u) self.update()
}
}
self.root.remove = function(e,u) self.root.remove = function(e,u)
{ {
var i = self.items.indexOf(e) var i = self.items.indexOf(e)

View File

@ -56,6 +56,11 @@
e.closable = self.closable e.closable = self.closable
self.refs.list.root.push(e,u) self.refs.list.root.push(e,u)
} }
self.root.replaceItem = function(o,n,u)
{
n.closable = self.closable
self.refs.list.root.replaceItem(o,n,u)
}
self.root.unshift = function(e,u) self.root.unshift = function(e,u)
{ {
self.refs.list.root.unshift(e,u) self.refs.list.root.unshift(e,u)

View File

@ -36,6 +36,12 @@ class BaseFileHandler
isRoot: () -> (not @genealogy) or (@genealogy.size is 0) isRoot: () -> (not @genealogy) or (@genealogy.size is 0)
child: (name) ->
if @isRoot()
return @path + name
else
return @path + "/" + name
isHidden: () -> isHidden: () ->
return false if not @basename return false if not @basename
@basename[0] is "." @basename[0] is "."
@ -44,10 +50,20 @@ class BaseFileHandler
return -1 unless @path return -1 unless @path
return @path.hash() return @path.hash()
getb64: (m) -> sendB64: (m, f) ->
return "" unless @cache me = @
return unless @cache
if typeof @cache is "string"
b64 = @cache.asBase64() b64 = @cache.asBase64()
return "data:#{m};base64,#{b64}" b64 = "data:#{m};base64,#{b64}"
f(b64)
else
reader = new FileReader()
reader.readAsDataURL(@cache)
reader.onload = () ->
f reader.result
reader.onerror = (e) ->
return _courrier.osfail "Cannot ecode file: #{me.path}", (_API.throwe "OS.VFS"), e
parent: () -> parent: () ->
return @ if @isRoot() return @ if @isRoot()
return (@protocol + ":///" + (@genealogy.slice 0 , @genealogy.length - 1).join "/") return (@protocol + ":///" + (@genealogy.slice 0 , @genealogy.length - 1).join "/")
@ -140,7 +156,8 @@ class RemoteFileHandler extends self.OS.API.VFS.BaseFileHandler
return f { error: "#{@path} is not a directory" } if @info.type is "file" return f { error: "#{@path} is not a directory" } if @info.type is "file"
_API.handler.mkdir "#{@path}/#{p}", f _API.handler.mkdir "#{@path}/#{p}", f
when "write" when "write"
_API.handler.write @path, p, f @sendB64 p, (data) ->
_API.handler.write me.path, data, f
when "upload" when "upload"
return if @info.type is "file" return if @info.type is "file"
_API.handler.upload @path, f _API.handler.upload @path, f

View File

@ -9,6 +9,7 @@ class GoogleDriveHandler extends this.OS.API.VFS.BaseFileHandler
@setting = _OS.setting.VFS.gdrive @setting = _OS.setting.VFS.gdrive
return _courrier.oserror "Unknown API setting for google drive VFS", (_API.throwe "OS.VFS"), null unless @setting return _courrier.oserror "Unknown API setting for google drive VFS", (_API.throwe "OS.VFS"), null unless @setting
@gid = 'root' if @isRoot() @gid = 'root' if @isRoot()
@cache = ""
oninit: (f) -> oninit: (f) ->
me = @ me = @
@ -28,6 +29,7 @@ class GoogleDriveHandler extends this.OS.API.VFS.BaseFileHandler
fn = (r) -> fn = (r) ->
return f() if r return f() if r
# perform the login # perform the login
G_CACHE = {"gdv:///":"root"}
gapi.auth2.getAuthInstance().signIn() gapi.auth2.getAuthInstance().signIn()
gapi.auth2.getAuthInstance().isSignedIn.listen (r) -> gapi.auth2.getAuthInstance().isSignedIn.listen (r) ->
@ -65,21 +67,49 @@ class GoogleDriveHandler extends this.OS.API.VFS.BaseFileHandler
fields: () -> fields: () ->
return "webContentLink, id, name,mimeType,description, kind, parents, properties, iconLink, createdTime, modifiedTime, owners, permissions, fullFileExtension, fileExtension, size" return "webContentLink, id, name,mimeType,description, kind, parents, properties, iconLink, createdTime, modifiedTime, owners, permissions, fullFileExtension, fileExtension, size"
isFolder: () ->
return @info.mimeType is "application/vnd.google-apps.folder"
save: (id, m, f) ->
me = @
user = gapi.auth2.getAuthInstance().currentUser.get()
oauthToken = user.getAuthResponse().access_token
xhr = new XMLHttpRequest()
url = 'https://www.googleapis.com/upload/drive/v3/files/' + id + '?uploadType=media'
xhr.open('PATCH', url)
xhr.setRequestHeader 'Authorization', 'Bearer ' + oauthToken
xhr.setRequestHeader 'Content-Type', m
xhr.setRequestHeader 'Content-Encoding', 'base64'
xhr.setRequestHeader 'Content-Transfer-Encoding', 'base64'
error = (e, s) ->
_courrier.oserror "VFS cannot save : #{me.path}", e, s
xhr.onreadystatechange = () ->
if ( xhr.readyState == 4 )
if ( xhr.status == 200 )
f { result: JSON.parse(xhr.responseText) }
else
error xhr, xhr.status
xhr.onerror = () ->
error xhr, xhr.status
@sendB64 m, (data) ->
xhr.send data.replace /^data:[^;]+;base64,/g, ""
action: (n, p, f) -> action: (n, p, f) ->
me = @ me = @
switch n switch n
when "read" when "read"
return unless @info.id return unless @info.id
if @info.mimeType is "application/vnd.google-apps.folder" if @isFolder()
gapi.client.drive.files.list { gapi.client.drive.files.list {
q: "'#{me.info.id}' in parents and trashed = false", q: "'#{me.info.id}' in parents and trashed = false",
fields: "files(#{me.fields()})" fields: "files(#{me.fields()})"
} }
.then (r) -> .then (r) ->
return unless r.result.files and r.result.files.length > 0 return unless r.result.files
for file in r.result.files for file in r.result.files
file.path = me.path + "/" + file.name file.path = me.child file.name
file.mime = file.mimeType file.mime = file.mimeType
file.filename = file.name file.filename = file.name
file.type = "file" file.type = "file"
@ -87,6 +117,7 @@ class GoogleDriveHandler extends this.OS.API.VFS.BaseFileHandler
if file.mimeType is "application/vnd.google-apps.folder" if file.mimeType is "application/vnd.google-apps.folder"
file.mime = "dir" file.mime = "dir"
file.type = "dir" file.type = "dir"
file.size = 0
f { result: r.result.files } f { result: r.result.files }
else else
gapi.client.drive.files.get { gapi.client.drive.files.get {
@ -97,19 +128,101 @@ class GoogleDriveHandler extends this.OS.API.VFS.BaseFileHandler
f r.body f r.body
when "mk" when "mk"
return f { error: "#{@path} is not a directory" } unless @isFolder()
meta =
name: p,
parents: [@info.id],
mimeType: 'application/vnd.google-apps.folder'
gapi.client.drive.files.create {
resource: meta,
fields: 'id'
}
.execute (r) ->
#console.log r
return _courrier.oserror "VFS cannot create : #{p}", (_API.throwe "OS.VFS"), r unless r and r.result
G_CACHE[me.child p] = r.result.id
f r
return return
when "write" when "write"
return gid = G_CACHE[me.path]
if gid
@save gid, p, f
else
console.log "New file"
dir = @parent().asFileHandler()
dir.onready () ->
meta =
name: me.basename,
mimeType: p,
parents: [dir.info.id]
gapi.client.drive.files.create {
resource: meta,
fields: 'id'
}
.execute (r) ->
return _courrier.oserror "VFS cannot write : #{me.path}", (_API.throwe "OS.VFS"), r unless r and r.result
G_CACHE[me.path] = r.result.id
me.save r.result.id, p, f
when "upload" when "upload"
return return unless @isFolder()
q = _courrier.getMID()
#insert a temporal file selector
o = ($ '<input>').attr('type', 'file').css("display", "none")
o.change () ->
#_API.loading q, p
fo = o[0].files[0]
file = (me.child fo.name).asFileHandler()
file.cache = fo
file.write fo.type, f
o.remove()
#_API.loaded q, p, "OK"
#_API.loaded q, p, "FAIL"
o.click()
when "remove" when "remove"
return return unless @info.id
gapi.client.drive.files.delete {
fileId: me.info.id
}
.execute (r) ->
#console.log r
return _courrier.oserror "VFS cannot delete : #{me.path}", (_API.throwe "OS.VFS"), r unless r
G_CACHE[me.path] = null
f { result: true }
when "publish" when "publish"
return return
when "download" when "download"
return gapi.client.drive.files.get {
fileId: me.info.id,
alt: 'media'
}
.then (r) ->
return _courrier.oserror "VFS cannot get file : #{me.path}", (_API.throwe "OS.VFS"), r unless r.body
blob = new Blob [r.body], { type: "octet/stream" }
_API.saveblob me.basename, blob
when "move" when "move"
return dest = p.asFileHandler().parent().asFileHandler()
dest.onready () ->
previousParents = me.info.parents.join ','
gapi.client.drive.files.update {
fileId: me.info.id,
addParents: dest.info.id,
removeParents: previousParents,
fields: "id"
}
.execute (r) ->
return _courrier.oserror "VFS cannot move : #{me.path}", (_API.throwe "OS.VFS"), r unless r
f r
else else
return _courrier.osfail "VFS unknown action: #{n}", (_API.throwe "OS.VFS"), n return _courrier.osfail "VFS unknown action: #{n}", (_API.throwe "OS.VFS"), n

View File

@ -88,6 +88,7 @@ class Files extends this.OS.GUI.BaseApplication
chdir: (p) -> chdir: (p) ->
me = @ me = @
console.log "ch"
dir = if p then p.asFileHandler() else me.currdir dir = if p then p.asFileHandler() else me.currdir
dir.read (d) -> dir.read (d) ->
if(d.error) if(d.error)
@ -102,7 +103,7 @@ class Files extends this.OS.GUI.BaseApplication
d.result.unshift p d.result.unshift p
($ me.navinput).val dir.path ($ me.navinput).val dir.path
me.view.set "path", dir.path me.view.set "path", dir.path
console.log d.result #console.log d.result
me.view.set "data", d.result me.view.set "data", d.result
mnFile:() -> mnFile:() ->
@ -252,7 +253,7 @@ class Files extends this.OS.GUI.BaseApplication
@openDialog "PromptDialog", @openDialog "PromptDialog",
(d) -> (d) ->
fp = "#{me.currdir.path}/#{d}".asFileHandler() fp = "#{me.currdir.path}/#{d}".asFileHandler()
fp.write "", (r) -> fp.write "text/plain", (r) ->
me.error "Fail to create #{d}: #{r.error}" if r.error me.error "Fail to create #{d}: #{r.error}" if r.error
, "New file", { label: "File name:" } , "New file", { label: "File name:" }

View File

@ -112,6 +112,7 @@ class NotePad extends this.OS.GUI.BaseApplication
open: (file) -> open: (file) ->
#find table #find table
i = @findTabByFile file i = @findTabByFile file
@fileview.set "preventUpdate", true
return @tabarea.set "selected", i if i isnt -1 return @tabarea.set "selected", i if i isnt -1
return @newtab file if file.path.toString() is "Untitled" return @newtab file if file.path.toString() is "Untitled"
me = @ me = @
@ -163,7 +164,7 @@ class NotePad extends this.OS.GUI.BaseApplication
save: (file) -> save: (file) ->
me = @ me = @
file.write (file.getb64 "text/plain"), (d) -> file.write "text/plain", (d) ->
return me.error "Error saving file #{file.basename}" if d.error return me.error "Error saving file #{file.basename}" if d.error
file.dirty = false file.dirty = false
file.text = file.basename file.text = file.basename
@ -191,7 +192,6 @@ class NotePad extends this.OS.GUI.BaseApplication
@currfile.selected = false @currfile.selected = false
file.selected = true file.selected = true
#console.log cnt #console.log cnt
@fileview.set "preventUpdate", true
@tabarea.push file, true @tabarea.push file, true
#@currfile = @file #@currfile = @file
#TODO: fix problem : @tabarea.set "selected", cnt #TODO: fix problem : @tabarea.set "selected", cnt
@ -255,7 +255,15 @@ class NotePad extends this.OS.GUI.BaseApplication
me = @ me = @
saveas = () -> saveas = () ->
me.openDialog "FileDiaLog", (d, n) -> me.openDialog "FileDiaLog", (d, n) ->
me.currfile.setPath "#{d}/#{n}" file = "#{d}/#{n}".asFileHandler()
file.cache = me.currfile.cache
file.dirty = me.currfile.dirty
file.um = me.currfile.um
file.cursor = me.currfile.cursor
file.selected = me.currfile.selected
file.text = me.currfile.text
me.tabarea.replaceItem me.currfile, file, false
me.currfile = file
me.save me.currfile me.save me.currfile
, "Save as", { file: me.currfile } , "Save as", { file: me.currfile }
switch e switch e