From 7dd617a524c85a14c266aa1568d3a9a77b791df5 Mon Sep 17 00:00:00 2001 From: vantezzen Date: Fri, 20 Dec 2019 19:21:22 +0100 Subject: #15 Add mastodon recipe --- all.json | 11 +++++ mastodon.tar.gz | Bin 0 -> 42658 bytes uncompressed/mastodon/LICENSE | 21 ++++++++++ uncompressed/mastodon/README.md | 71 ++++++++++++++++++++++++++++++++ uncompressed/mastodon/icon.png | Bin 0 -> 40205 bytes uncompressed/mastodon/icon.svg | 1 + uncompressed/mastodon/index.js | 53 ++++++++++++++++++++++++ uncompressed/mastodon/package.json | 17 ++++++++ uncompressed/mastodon/webview.js | 82 +++++++++++++++++++++++++++++++++++++ 9 files changed, 256 insertions(+) create mode 100644 mastodon.tar.gz create mode 100644 uncompressed/mastodon/LICENSE create mode 100644 uncompressed/mastodon/README.md create mode 100644 uncompressed/mastodon/icon.png create mode 100644 uncompressed/mastodon/icon.svg create mode 100644 uncompressed/mastodon/index.js create mode 100644 uncompressed/mastodon/package.json create mode 100644 uncompressed/mastodon/webview.js diff --git a/all.json b/all.json index 44ec489..f33eb0d 100644 --- a/all.json +++ b/all.json @@ -834,5 +834,16 @@ "png": "https://cdn.jsdelivr.net/gh/getferdi/recipes/uncompressed/instagram/icon.png", "svg": "https://cdn.jsdelivr.net/gh/getferdi/recipes/uncompressed/instagram/icon.svg" } + }, + { + "author": "sharkpp ", + "featured": false, + "id": "mastodon", + "name": "Mastodon", + "version": "1.0.1", + "icons": { + "png": "https://cdn.jsdelivr.net/gh/getferdi/recipes/uncompressed/mastodon/icon.png", + "svg": "https://cdn.jsdelivr.net/gh/getferdi/recipes/uncompressed/mastodon/icon.svg" + } } ] diff --git a/mastodon.tar.gz b/mastodon.tar.gz new file mode 100644 index 0000000..299c229 Binary files /dev/null and b/mastodon.tar.gz differ diff --git a/uncompressed/mastodon/LICENSE b/uncompressed/mastodon/LICENSE new file mode 100644 index 0000000..aabad64 --- /dev/null +++ b/uncompressed/mastodon/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 sharkpp. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/uncompressed/mastodon/README.md b/uncompressed/mastodon/README.md new file mode 100644 index 0000000..b0477b6 --- /dev/null +++ b/uncompressed/mastodon/README.md @@ -0,0 +1,71 @@ +# Mastodon for Franz 5 + +This is the [Franz](https://meetfranz.com/) 5 recipe for Mastodon + +## REQUIRED + +* [Franz](https://meetfranz.com/) 5 or later + Do not support older version. +* [Mastodon](https://joinmastodon.org/) account + Do not have an account? + Choose from "[Mastodon instances](https://instances.social/list)"! + +## HOW TO INSTALL + +### DEVELOP VERSION + +1. download the `franz-recipe-mastodon` folder. +2. Open the Franz Plugins folder on your machine (note **that this `dev` directory may not exist yet, and you must create it**): + * Mac: `~/Library/Application Support/Franz/recipes/dev/` + * Windows: `%AppData%\Franz\recipes\dev\` + * Linux: `~/.config/Franz/recipes/dev` +3. Copy the `franz-recipe-mastodon` folder into the plugins directory +4. Reload Franz + +See [Franz Recipe Documentation / Overview](https://github.com/meetfranz/plugins/blob/master/docs/integration.md) + for details. + +### STABLE VERSION + +*Coming Soon ...* + +## USAGE + +### ADD NEW SERVICE + +![](docs/add-service.png) + +*develop version* + +### SETTINGS + +![](docs/add-service-settings.png) + +| # | field | description | +|-|-|-| +| (1) | service name | Please set freely | +| (2) | Mastodon host | Please enter the host on which Mastodon is running. Only https is supported. | + +### SIGN-IN + +![](docs/mstdn_jp-signin.png) + +Please enter registered account information. + +### NOTIFICATION BADGE + +![](docs/notification-badge-example.png) + +In order to use it, desktop notification must be enabled on *mastodon* side. + +| current actived service | clear badge | +|-|-| +| this service | At the end of 10 seconds from the last notice | +| other service | this service actived | + + +## LICENSE + +© 2018 sharkpp + +This software is licensed under a [The MIT License](http://opensource.org/licenses/MIT). diff --git a/uncompressed/mastodon/icon.png b/uncompressed/mastodon/icon.png new file mode 100644 index 0000000..a26dcd5 Binary files /dev/null and b/uncompressed/mastodon/icon.png differ diff --git a/uncompressed/mastodon/icon.svg b/uncompressed/mastodon/icon.svg new file mode 100644 index 0000000..4b72b3a --- /dev/null +++ b/uncompressed/mastodon/icon.svg @@ -0,0 +1 @@ + diff --git a/uncompressed/mastodon/index.js b/uncompressed/mastodon/index.js new file mode 100644 index 0000000..a2ca0b7 --- /dev/null +++ b/uncompressed/mastodon/index.js @@ -0,0 +1,53 @@ +//'use strict'; + +module.exports = Franz => class Mastodon extends Franz { + + constructor(...args) { + let _temp; + // + let serviceCache = {}; + // send service store for webview + setInterval(() => { + if (!window.franz) { // not present(near equal not initialize) + return; + } + const services = window.franz.stores.services; + // filter this recipe class + const instancedServices = services.all.filter(service => service.recipe.constructor === this.constructor); + // send + instancedServices.forEach(service => { + let updated = false; + serviceCache[service.id] = Object.keys(service).reduce((r, key) => { + if (!service[key] || Object !== service[key].constructor) { + updated = updated || serviceCache[key] !== service[key]; + r[key] = service[key]; + } + return r; + }, serviceCache[service.id] || {}); + if (updated) { + service.webview.send('-service-update', service); + } + }); + }, 1000); + return _temp = super(...args), this.events = { + }, _temp; + } + + async validateUrl(url) { + try { + const res = await window.fetch(`${url}/api/v1/instance/`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + const data = await res.json(); + // check url field in API response + return Object.hasOwnProperty.call(data, 'uri'); + } catch (err) { + console.error(err); + } + return false; + } + +}; diff --git a/uncompressed/mastodon/package.json b/uncompressed/mastodon/package.json new file mode 100644 index 0000000..84a17e8 --- /dev/null +++ b/uncompressed/mastodon/package.json @@ -0,0 +1,17 @@ +{ + "id": "mastodon", + "name": "Mastodon", + "version": "1.0.1", + "description": "Mastodon recipe for Franz 5 or later", + "main": "index.js", + "author": "sharkpp ", + "license": "MIT", + "repository": "https://github.com/sharkpp/franz-recipe-mastodon", + "config": { + "serviceURL": "https://{teamId}", + "hasTeamId": true, + "hasNotificationSound": true, + "hasIndirectMessages": false, + "message": "Please enter the instance address of Mastodon in the team name input box." + } +} diff --git a/uncompressed/mastodon/webview.js b/uncompressed/mastodon/webview.js new file mode 100644 index 0000000..dcf715e --- /dev/null +++ b/uncompressed/mastodon/webview.js @@ -0,0 +1,82 @@ +//'use strict'; + +const { ipcRenderer } = require('electron'); + +const BADGE_AUTO_CLEAR_DELAY = 10000; // delay time for badge clear auto + +// MONKEY PATCH: +// fix 'Uncaught TypeError: c.addEventListener is not a function' +// from mastdon code +// see https://github.com/tootsuite/mastodon/blob/c1a41181c52216de9ebeecebf418e6d50172139b/app/javascript/mastodon/actions/notifications.js#L60 +if (!Notification.prototype.addEventListener) { + Notification.prototype.addEventListener = function(){}; +} + +module.exports = (Franz, service_) => { + + let service = service_; + + // save service instance identify + const serviceId = service.id; + + // check if this service is active + let activeUpdated = false; + let isActive = service.isActive; + + ipcRenderer.on('-service-update', (sender, serviceNew) => { + service = serviceNew; + !activeUpdated && (activeUpdated = isActive != service.isActive); + isActive = service.isActive; + }); + + //ipcRenderer.on('settings-update', (sender, settings) => { + // const nextIsActive = serviceId == settings.activeService; + // !activeUpdated && (activeUpdated = isActive != nextIsActive); + // isActive = nextIsActive; + //}); + + let replyCount = 0; + let limitBadgeClear = false; + + const getMessages = function getMessages() { + const activeUpdated_ = activeUpdated; activeUpdated = false; + + // check and redirect to signin page when not loggdin + if (window.location && /\/about$/.test(window.location.pathname)) { + const hasSigninLink = !!document.querySelector('[href$="/auth/sign_in"]'); + if (hasSigninLink) { + window.location.pathname = '/auth/sign_in'; + return; + } + } + + // clear replay badge when ... + if (replyCount) { + // this service actived + if (activeUpdated_ && isActive) { + replyCount = 0; + } + // timeout + if (!isActive && limitBadgeClear) { + limitBadgeClear = false; + } + if (isActive && false !== limitBadgeClear && limitBadgeClear <= Date.now()) { + replyCount = 0; + limitBadgeClear = false; + } + } + + Franz.setBadge(replyCount); + }; + + Franz.loop(getMessages); + + Franz.onNotify(notification => { + // increment reply count for badge + ++replyCount; + limitBadgeClear = Date.now() + BADGE_AUTO_CLEAR_DELAY; + // + return notification; + + }); +}; \ No newline at end of file -- cgit v1.2.3-70-g09d2