diff --git a/apps/reply/ChangeLog b/apps/reply/ChangeLog new file mode 100644 index 000000000..f3c7b0d2c --- /dev/null +++ b/apps/reply/ChangeLog @@ -0,0 +1 @@ +0.01: New Library! \ No newline at end of file diff --git a/apps/reply/README.md b/apps/reply/README.md new file mode 100644 index 000000000..dc874d183 --- /dev/null +++ b/apps/reply/README.md @@ -0,0 +1,23 @@ +# Canned Replies Library + +A library that handles replying to messages received from Gadgetbridge/Messages apps. + +## Replying to a message +The user can define a set of canned responses via the customise page after installing the app, or alternatively if they have a keyboard installed, they can type a response back. The requesting app will receive either an object containing the full reply for GadgetBridge, or a string with the response from the user, depending on how they wish to handle the response. + +## Integrating in your app +To use this in your app, simply call + +```js +require("reply").reply(/*options*/{...}).then(result => ...); +``` + +The ```options``` object can contain the following: + +- ```msg```: A message object containing a field ```id```, the ID to respond to. If this is included in options, the result of the promise will be an object as follows: ```{t: "notify", id: msg.id, n: "REPLY", msg: "USER REPLY"}```. If not included, the result of the promise will be an object, ```{msg: "USER REPLY"}``` +- ```shouldReply```: Whether or not the library should send the response over Bluetooth with ```Bluetooth.println(...```. Useful if the calling app wants to handle the response a different way. Default is true. +- ```title```: The title to show at the top of the menu. Defaults to ```"Reply with:"```. +- ```fileOverride```: An override file to read canned responses from, which is an array of objects each with a ```text``` property. Default is ```replies.json```. Useful for apps which might want to make use of custom canned responses. + +## Known Issues +Emojis are currently not supported. \ No newline at end of file diff --git a/apps/reply/app.png b/apps/reply/app.png new file mode 100644 index 000000000..bef8338cf Binary files /dev/null and b/apps/reply/app.png differ diff --git a/apps/reply/interface.html b/apps/reply/interface.html new file mode 100644 index 000000000..2034a1195 --- /dev/null +++ b/apps/reply/interface.html @@ -0,0 +1,125 @@ + + + + + + + + +
+ + + +
+
+
+ +
+
+
+
+
+
+

Loading

+

Syncing custom replies with your watch

+
+
+
+
+
+ +
+

No custom replies

+

Use the field above to add a custom reply

+
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/apps/reply/lib.js b/apps/reply/lib.js new file mode 100644 index 000000000..7bd4780a5 --- /dev/null +++ b/apps/reply/lib.js @@ -0,0 +1,75 @@ +exports.reply = function (options) { + var keyboard = "textinput"; + try { + keyboard = require(keyboard); + } catch (e) { + keyboard = null; + } + + function constructReply(msg, replyText, resolve) { + var responseMessage = {msg: replyText}; + if (msg.id) { + responseMessage = { t: "notify", id: msg.id, n: "REPLY", msg: replyText }; + } + E.showMenu(); + layout.setUI(); + layout.render(); + if (options.sendReply == null || options.sendReply) { + Bluetooth.println(JSON.stringify(result)); + } + resolve(responseMessage); + } + + return new Promise((resolve, reject) => { + var menu = { + "": { + title: options.title || /*LANG*/ "Reply with:", + back: function () { + E.showMenu(); + layout.setUI(); + layout.render(); + reject("User pressed back"); + }, + }, // options + /*LANG*/ "Compose": function () { + keyboard.input().then((result) => { + constructReply(options.msg ?? {}, result, resolve); + }); + }, + }; + var replies = + require("Storage").readJSON( + options.fileOverride || "replies.json", + true + ) || {}; + replies.forEach((reply) => { + menu = Object.defineProperty(menu, reply.text, { + value: () => constructReply(options.msg ?? {}, reply.text, resolve), + }); + }); + if (!keyboard) delete menu[/*LANG*/ "Compose"]; + + if (replies.length == 0) { + if (!keyboard) { + E.showPrompt( + /*LANG*/ "Please install a keyboard app, or set a custom reply via the app loader!", + { + buttons: { Ok: true }, + remove: function () { + layout.setUI(); + layout.render(); + reject( + "Please install a keyboard app, or set a custom reply via the app loader!" + ); + }, + } + ); + } else { + keyboard.input().then((result) => { + constructReply(options.msg.id, result, resolve); + }); + } + } + E.showMenu(menu); + }); +}; diff --git a/apps/reply/metadata.json b/apps/reply/metadata.json new file mode 100644 index 000000000..34843edd4 --- /dev/null +++ b/apps/reply/metadata.json @@ -0,0 +1,16 @@ +{ "id": "reply", + "name": "Reply Library", + "version": "0.01", + "description": "A library for replying to text messages via predefined responses or keyboard", + "icon": "app.png", + "type": "module", + "provides_modules" : ["reply"], + "tags": "", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "interface": "interface.html", + "storage": [ + {"name":"reply","url":"lib.js"} + ], + "data": [{"name":"replies.json"}] +} \ No newline at end of file