Libreoffice: improvement + add features

This commit is contained in:
lxsang 2022-08-24 13:34:57 +02:00
parent 6e020484a8
commit 96ef0ac0de
10 changed files with 177 additions and 30 deletions

View File

@ -9,4 +9,9 @@ It support a wide range of documents.
![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true) ![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true)
## Change log ## Change log
- v 0.1.1-a:
* improve UI handling
* add Save as option
* add traditional AntOS application File menu
* fetch supported mimes from discovery URL
- v 0.1.0-a: Initial version - v 0.1.0-a: Initial version

View File

@ -1,11 +1,14 @@
local args=... local args=...
--LOG_ROOT = ulib.getenv("HOME")
if not args then if not args then
args = REQUEST args = REQUEST
end end
local vfs = require("vfs") local vfs = require("vfs")
local DLCMD="wget --no-check-certificate -O" local DLCMD="wget --no-check-certificate -O"
local handle = {} local handle = {}
--local logger = Logger:new{ levels = {INFO = true, ERROR = true, DEBUG = false}}
local result = function(data) local result = function(data)
return { error = false, result = data } return { error = false, result = data }
end end
@ -24,6 +27,21 @@ handle.token = function(data)
return result(ret) return result(ret)
end end
handle.duplicate = function(data)
if not data.src or not data.dest then
return error("Unknow source or destination file")
end
local real_src = vfs.ospath(data.src)
local real_dest = vfs.ospath(data.dest)
if not ulib.exists(real_src) then
return error("Source file doesnt exist")
end
if not ulib.send_file(real_src, real_dest) then
return error("Unable to duplicate file")
end
return result(true)
end
handle.discover = function(data) handle.discover = function(data)
local tmpfile = "/tmp/libreoffice_discover.xml" local tmpfile = "/tmp/libreoffice_discover.xml"
local cmd = DLCMD.." "..tmpfile..' '..data.uri local cmd = DLCMD.." "..tmpfile..' '..data.uri
@ -67,7 +85,8 @@ handle.file = function(data)
Size = math.floor(stat.size), Size = math.floor(stat.size),
UserCanWrite = vfs.checkperm(data.file,"write"), UserCanWrite = vfs.checkperm(data.file,"write"),
mime = stat.mime, mime = stat.mime,
PostMessageOrigin = "*" PostMessageOrigin = "*",
UserCanNotWriteRelative = false
} }
else else
return error("Unknown request") return error("Unknown request")
@ -75,6 +94,8 @@ handle.file = function(data)
end end
--logger:info(JSON.encode(REQUEST))
if args.action and handle[args.action] then if args.action and handle[args.action] then
return handle[args.action](args.args) return handle[args.action](args.args)
else else

View File

@ -9,4 +9,9 @@ It support a wide range of documents.
![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true) ![https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true](https://github.com/lxsang/antosdk-apps/blob/master/LibreOffice/libreoffice.png?raw=true)
## Change log ## Change log
- v 0.1.1-a:
* improve UI handling
* add Save as option
* add traditional AntOS application File menu
* fetch supported mimes from discovery URL
- v 0.1.0-a: Initial version - v 0.1.0-a: Initial version

View File

@ -1,11 +1,14 @@
local args=... local args=...
--LOG_ROOT = ulib.getenv("HOME")
if not args then if not args then
args = REQUEST args = REQUEST
end end
local vfs = require("vfs") local vfs = require("vfs")
local DLCMD="wget --no-check-certificate -O" local DLCMD="wget --no-check-certificate -O"
local handle = {} local handle = {}
--local logger = Logger:new{ levels = {INFO = true, ERROR = true, DEBUG = false}}
local result = function(data) local result = function(data)
return { error = false, result = data } return { error = false, result = data }
end end
@ -24,6 +27,21 @@ handle.token = function(data)
return result(ret) return result(ret)
end end
handle.duplicate = function(data)
if not data.src or not data.dest then
return error("Unknow source or destination file")
end
local real_src = vfs.ospath(data.src)
local real_dest = vfs.ospath(data.dest)
if not ulib.exists(real_src) then
return error("Source file doesnt exist")
end
if not ulib.send_file(real_src, real_dest) then
return error("Unable to duplicate file")
end
return result(true)
end
handle.discover = function(data) handle.discover = function(data)
local tmpfile = "/tmp/libreoffice_discover.xml" local tmpfile = "/tmp/libreoffice_discover.xml"
local cmd = DLCMD.." "..tmpfile..' '..data.uri local cmd = DLCMD.." "..tmpfile..' '..data.uri
@ -67,7 +85,8 @@ handle.file = function(data)
Size = math.floor(stat.size), Size = math.floor(stat.size),
UserCanWrite = vfs.checkperm(data.file,"write"), UserCanWrite = vfs.checkperm(data.file,"write"),
mime = stat.mime, mime = stat.mime,
PostMessageOrigin = "*" PostMessageOrigin = "*",
UserCanNotWriteRelative = false
} }
else else
return error("Unknown request") return error("Unknown request")
@ -75,6 +94,8 @@ handle.file = function(data)
end end
--logger:info(JSON.encode(REQUEST))
if args.action and handle[args.action] then if args.action and handle[args.action] then
return handle[args.action](args.args) return handle[args.action](args.args)
else else

File diff suppressed because one or more lines are too long

View File

@ -7,7 +7,7 @@
"author": "Dany LE", "author": "Dany LE",
"email": "contact@iohub.dev" "email": "contact@iohub.dev"
}, },
"version":"0.1.0-a", "version":"0.1.1-a",
"category":"Office", "category":"Office",
"icon":"icon.png", "icon":"icon.png",
"mimes":[ "mimes":[

View File

@ -16,8 +16,10 @@ namespace OS {
private placeholder: HTMLDivElement; private placeholder: HTMLDivElement;
private eid: string; private eid: string;
private iframe: HTMLIFrameElement; private iframe: HTMLIFrameElement;
private editor_meta: GenericObject<any>; private editor_meta: GenericObject<GenericObject<string>>;
private post_msg_handle: (e:any) => void; private post_msg_handle: (e:any) => void;
private mimes: string[];
private current_mode: string;
static discovery_uri: string; static discovery_uri: string;
constructor(args: AppArgumentsType[]) { constructor(args: AppArgumentsType[]) {
@ -26,6 +28,8 @@ namespace OS {
this.curr_file = undefined; this.curr_file = undefined;
this.eid = `id${Math.random().toString(36).replace(".","")}`; this.eid = `id${Math.random().toString(36).replace(".","")}`;
this.iframe = undefined; this.iframe = undefined;
this.mimes = this.meta().mimes.map(e=>e);
this.current_mode = undefined;
this.post_msg_handle = (e) => this.post_msg_handle = (e) =>
{ {
this.process_iframe_msg(e); this.process_iframe_msg(e);
@ -44,8 +48,6 @@ namespace OS {
{ {
this.openFile(); this.openFile();
} }
(this.find("btn-new-doc") as GUI.tag.ButtonTag).onbtclick = (e) => (this.find("btn-new-doc") as GUI.tag.ButtonTag).onbtclick = (e) =>
{ {
this.create("word"); this.create("word");
@ -73,6 +75,46 @@ namespace OS {
this.quit(true); this.quit(true);
}); });
} }
menu(): OS.GUI.BasicItemType[]{
const nodes = [
{ text: "__(New)", dataid :"new" },
{ text: "__(Open)", dataid :"open" }
]
if(this.current_mode == "edit")
{
nodes.push({ text: "__(Save)", dataid :"save"});
nodes.push({ text: "__(Save As)", dataid :"saveas"});
}
return [
{
text: "__(File)",
nodes: nodes,
onchildselect: (e) =>
{
switch(e.data.item.data.dataid)
{
case "new":
this.check_dirty().then((_)=>this.new_document());
break;
case "open":
this.check_dirty().then((_)=>this.openFile());
break;
case "save":
this.post_message("Action_Save", {
DontTerminateEdit: true,
DontSaveIfUnmodified: true,
Notify: true
});
break;
case "saveas":
this.check_dirty().then((_)=>this.save_as());
break;
default:
}
}
}
]
}
private update_title() private update_title()
{ {
let title = this.curr_file.path; let title = this.curr_file.path;
@ -84,7 +126,6 @@ namespace OS {
} }
private post_message(id:string, values?: GenericObject<any>) private post_message(id:string, values?: GenericObject<any>)
{ {
console.log("sending",id);
let msg:GenericObject<any> = {MessageId: id,SendTime: Date.now()}; let msg:GenericObject<any> = {MessageId: id,SendTime: Date.now()};
if(values) if(values)
msg.Values = values; msg.Values = values;
@ -109,7 +150,9 @@ namespace OS {
{ {
this.post_message("Host_PostmessageReady"); this.post_message("Host_PostmessageReady");
this.trigger("document_file_loaded"); this.trigger("document_file_loaded");
this.post_message("Insert_Button", if(this.current_mode == "edit")
{
this.post_message("Insert_Button",
{ {
id:'lool_new_file', id:'lool_new_file',
imgurl:BUTTON_ICONS.newdoc, imgurl:BUTTON_ICONS.newdoc,
@ -117,16 +160,17 @@ namespace OS {
hint: __("Create new document").__(), hint: __("Create new document").__(),
insertBefore: 'save' insertBefore: 'save'
} }
); );
this.post_message("Insert_Button", this.post_message("Insert_Button",
{ {
id:'lool_open_file', id:'lool_open_file',
imgurl:BUTTON_ICONS.opendoc, imgurl:BUTTON_ICONS.opendoc,
label: __("Open file").__(), label: __("Open file").__(),
hint: __("Open document").__(), hint: __("Open document").__(),
insertBefore: 'lool_new_file' insertBefore: 'lool_new_file'
} }
); );
}
} }
if(data.Values.Status == "Frame_Ready") if(data.Values.Status == "Frame_Ready")
{ {
@ -149,12 +193,44 @@ namespace OS {
default: default:
} }
break; break;
case "UI_SaveAs":
this.check_dirty().then((_)=>this.save_as());
break;
default: default:
console.log(data); console.log(data);
} }
//console.log(this.eid, e); //console.log(this.eid, e);
} }
private save_as()
{
this.openDialog("FileDialog", {
title: __("Save file as"),
type: "dir",
file: this.curr_file.asFileHandle()
})
.then(async (d) => {
const file = `${d.file.path}/${d.name}`.asFileHandle();
try
{
const r = await this.exec({
action: 'duplicate',
args:{src: this.curr_file.path, dest: file.path}
});
if(r.error)
{
throw r.error;
}
this.curr_file = file;
this.open();
}
catch(e)
{
this.error(__("Unable to save file as {0}: {1}", file.path, e.toString()),e);
}
});
}
private new_document() private new_document()
{ {
this.openDialog("SelectionDialog", { this.openDialog("SelectionDialog", {
@ -194,16 +270,29 @@ namespace OS {
if(apps) if(apps)
{ {
for(let app of apps){ for(let app of apps){
let name = app.getAttribute("name")
if(name.match(/^[^\/]*\/[^\/]*$/g))
{
if(!(this.mimes as any).includes(name))
{
this.mimes.push(name);
}
}
let actions = app.getElementsByTagName("action"); let actions = app.getElementsByTagName("action");
if(actions) if(actions)
{ {
for(let action of actions) for(let action of actions)
{ {
let ext = action.getAttribute("ext"); let ext = action.getAttribute("ext");
let mode = action.getAttribute("name");
let urlsrc = action.getAttribute("urlsrc"); let urlsrc = action.getAttribute("urlsrc");
if(ext && ext != "" && urlsrc) if(ext && ext != "" && urlsrc)
{ {
meta[ext] = urlsrc; meta[ext] =
{
url: urlsrc,
mode: mode
}
} }
} }
} }
@ -222,7 +311,7 @@ namespace OS {
this.openDialog("FileDialog", { this.openDialog("FileDialog", {
title: __("Open file"), title: __("Open file"),
type: "file", type: "file",
mimes: this.meta().mimes mimes: this.mimes
}) })
.then((d) => .then((d) =>
{ {
@ -292,14 +381,17 @@ namespace OS {
return; return;
} }
this.access_token = r.result.sid; this.access_token = r.result.sid;
let url = this.editor_meta[this.curr_file.ext]; let mt = this.editor_meta[this.curr_file.ext];
if(!url) if(!mt || !mt.url)
{ {
return this.error(__("Unknown editor for extension {0}", this.curr_file.ext)); return this.error(__("Unknown editor for extension {0}", this.curr_file.ext));
} }
this.current_mode = mt.mode;
// refresh the file menu
this.appmenu.items = this.baseMenu() || [];
$(this.placeholder).empty(); $(this.placeholder).empty();
let el = $('<iframe>', { let el = $('<iframe>', {
src: `${url}?WOPISrc=${this.uapi()}`, src: `${mt.url}?WOPISrc=${this.uapi()}`,
frameborder: 0 frameborder: 0
}); });
this.iframe = el[0] as HTMLIFrameElement; this.iframe = el[0] as HTMLIFrameElement;
@ -353,7 +445,6 @@ namespace OS {
.then((d) => .then((d) =>
{ {
if(!d) return; if(!d) return;
this.curr_file.dirty = false;
ok(true); ok(true);
}); });
} }
@ -368,7 +459,11 @@ namespace OS {
if(this.curr_file && this.curr_file.dirty) if(this.curr_file && this.curr_file.dirty)
{ {
e.preventDefault(); e.preventDefault();
this.check_dirty().then((_)=>this.quit(true)); this.check_dirty().then((_)=>{
this.curr_file.dirty = false;
this.quit(true);
}
);
return; return;
} }
$(window).off("message",this.post_msg_handle); $(window).off("message",this.post_msg_handle);

View File

@ -7,7 +7,7 @@
"author": "Dany LE", "author": "Dany LE",
"email": "contact@iohub.dev" "email": "contact@iohub.dev"
}, },
"version":"0.1.0-a", "version":"0.1.1-a",
"category":"Office", "category":"Office",
"icon":"icon.png", "icon":"icon.png",
"mimes":[ "mimes":[

View File

@ -265,7 +265,7 @@
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/LibreOffice/README.md", "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/LibreOffice/README.md",
"category": "Office", "category": "Office",
"author": "Dany LE", "author": "Dany LE",
"version": "0.1.0-a", "version": "0.1.1-a",
"dependencies": [], "dependencies": [],
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/LibreOffice/build/release/LibreOffice.zip" "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/LibreOffice/build/release/LibreOffice.zip"
}, },