Description
I propose an addition to the Sailfish.Share protocol (not necessarily implementation) to allow the sending application to include hint data for the receiving application.
Something like this is already implemented in the context of the Webview Share context, in the form of the linkText
and sister properties, but is specialized for sharing URLs.
My proposed feature generalizes the approach, and does not need changes to Sailfish.Share
(but does require changes to applications receiving ShareAction data).
In fact, this proposes more of a convention than a feature.
Background
While working on Bugger! i came across the problem of wanting to send an email, and include both a Subject and Recipient, and attachments,
It turns out while Sailfish.Share will allow for text to be placed in the email body (in addition to adding files as attachments), I have found no way to add other basic email data such as recipient.
(There is also the possibility to use Qt.openURLExternally(mailto:...)
, which allows to specify recipients and subjects, but no attachments can be added).
Such came the need to have Sailfish.Share transport “hint” or “metadata” in addition to the pure file data. Not only for the email case, but in general.
RFC: Specification
ShareAction senders
As one of the elements of the ShareAction::resources
array, include objects of the format:
{ "type": "text/x-sailfish-share-hints", "appHint": dataString }
with dataString
being a JSON string of the format:
{ "type" : "", "data": {} }
where type
is a string of the intended target application type, such as “email”, “browser”, “messenger”, or the special string “generic”. This is intended to be used by applications handling the hints to ignore those that don’t fit their purpose.
If the type
is “email”, data
must be of the format:
{
"to": "",
"cc": "",
"bcc": "",
"subject": ""
}
(perhaps body
should also be part of this set, but the current implementation of jolla-email
already has other ways of adding body data, i.e. using a resource
of type “text/plain”.).
However, IF body
was added to this format, and the additional properties of Content-Type
and Content-Encoding
this could allow for completely formatted emails with arbitrary Multipart/MIME structure to be passed. But this would need extensive changes to jolla-email
.
If the type
is “generic”, data
must be of the format:
{
"context": ""
"recipient": "",
"summary": "",
"description": ""
}
Where context
might be used to refer to any of the other elements of the Sailfish.Share::resources
. This could be used to e.g. give textual descriptions to images shared. However, how the contents of context
and any element of resources
might be matched up is undefined. This might be e.g. a file name, checksum, or some internal metadata of the file.
recipient
is a “logical receiver” of the shared content. This might be and URL string (e.g. if the files should be uploaded at some web location), a name (such as an email address), or something like the UID of an instant messaging contact).
summary
and description
are single-line and multi-line (respectively) text.
ShareAction receivers
As an example, see the handling of shared data in /usr/share/jolla-email/email.qml
(DBus interface to receive shared data), and /usr/share/jolla-email/pages/ShareComposerPage.qml
(handling the data).
Applications should iterate over the received resources and
- look for entries having a type of
text/x-sailfish-share-hints
- if present, load the contents of the
appHint
property, and parse its JSON string. - read the
appHint.type
, for types the application knows how to handle - use the contents of the
appHint.data
object as appropriate
PoC: Implementation for jolla-email
Consider the following:
ShareAction { id: sharer
mimeType: "text/x-url" // reduces the share-with application list to "email" and a couple of others
}
ListModel { id: filesModel
ListElement { name: "Test File 1"; filePath: "path/to/a/test/file" }
ListElement { name: "Test File 2"; filePath: "path/to/another/file" }
}
function emailshare() {
const body = 'There should be ' + filesModel.count + ' files attached.\n\n'
const appHint = {
"type" : "email",
"data": {
"to": "max@example.org"
"cc": "",
"bcc": "",
"subject": "Hello Sailor!"
}
}
var res = [
{ "type": "text/x-url", "linkTitle": body }, // this is one of the current ways to add body text to an email
{ "type": "text/x-sailfish-share-hints", "appHint": JSON.stringify(appHint) }
];
for (var i = 0; i < filesModel.count; ++i) {
const f = filesModel.get(i)
res.push( f.filePath )
}
sharer.resources = res;
sharer.trigger();
}
For this to work, you need this small patch against jolla-email
:
diff -Naur work/4.4.0.72/usr/share/jolla-email/pages/ShareComposerPage.qml work/4.4.0.72_mine/usr/share/jolla-email/pages/ShareComposerPage.qml
--- /usr/share/jolla-email/pages/ShareComposerPage.qml 2022-12-10 19:03:55.822739406 +0100
+++ /usr/share/jolla-email/pages/ShareComposerPage.qml 2022-12-10 21:54:57.200451067 +0100
@@ -54,7 +54,7 @@
for (var i = 0; i < resources.length; ++i) {
if (typeof resources[i] === "string") {
_fileResources.push(resources[i])
- } else if (resources[i].type === "text/plain" || resources[i].type === "text/x-url") {
+ } else if (resources[i].type === "text/plain" || resources[i].type === "text/x-url" || resources[i].type === "text/x-sailfish-share-hints") {
// Show the contents inline within the email.
_contentResources.push(resources[i])
} else {
@@ -95,11 +95,27 @@
Component.onCompleted: {
var content = modelData
- if (content.type !== "text/plain" && content.type !== "text/x-url") {
+ if (content.type !== "text/plain" && content.type !== "text/x-url" && content.type !== "text/x-sailfish-share-hints") {
// Other file types should have been converted into temporary files by ShareAction.
console.warn("Unexpected inline email content type:", content.type)
return
}
+ if (content.type === "text/x-sailfish-share-hints") {
+ try {
+ // TODO: can we use an Object instead?
+ var appHint = JSON.parse(content.appHint)
+ if (appHint && appHint.hasOwnProperty("type") && appHint["type"] === "email") {
+ var hintData = appHint["data"]
+ root.emailTo = hintData.to
+ root.emailCc = hintData.cc
+ root.emailBcc = hintData.bcc
+ root.emailSubject = hintData.subject
+ }
+ } catch (exception) {
+ console.warn("Cound not parse application hints.")
+ return
+ }
+ }
if (content.type === "text/x-url" && content.linkTitle) {
root.emailBody += (content.linkTitle + "\n\n")
}
I would have made pull requests against both the Share docs as well as Mail app instead of posting this here - alas there is no open source repository to to this.