From 4875e0974098ad4cd9fdb32f487cbc52a3f3ebf2 Mon Sep 17 00:00:00 2001 From: smpl Date: Fri, 29 Apr 2022 23:52:47 +0200 Subject: [PATCH] ENERGIZE! --- LICENSE | 18 +++ README | 70 ++++++++++ mastodon-follow-dark-da.js | 210 ++++++++++++++++++++++++++++++ mastodon-follow-dark-da.svg | 33 +++++ mastodon-follow-dark-en.js | 210 ++++++++++++++++++++++++++++++ mastodon-follow-dark-en.svg | 37 ++++++ mastodon-follow-dark.svg | 24 ++++ mastodon-follow-light-da.js | 210 ++++++++++++++++++++++++++++++ mastodon-follow-light-da.svg | 33 +++++ mastodon-follow-light-en.js | 210 ++++++++++++++++++++++++++++++ mastodon-follow-light-en.svg | 37 ++++++ mastodon-follow-light.svg | 24 ++++ mastodon-follow.js | 242 +++++++++++++++++++++++++++++++++++ 13 files changed, 1358 insertions(+) create mode 100644 LICENSE create mode 100644 README create mode 100644 mastodon-follow-dark-da.js create mode 100644 mastodon-follow-dark-da.svg create mode 100644 mastodon-follow-dark-en.js create mode 100644 mastodon-follow-dark-en.svg create mode 100644 mastodon-follow-dark.svg create mode 100644 mastodon-follow-light-da.js create mode 100644 mastodon-follow-light-da.svg create mode 100644 mastodon-follow-light-en.js create mode 100644 mastodon-follow-light-en.svg create mode 100644 mastodon-follow-light.svg create mode 100644 mastodon-follow.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3167117 --- /dev/null +++ b/LICENSE @@ -0,0 +1,18 @@ +Copyright (C) 2022 smpl + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would + be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +3. This notice may not be removed or altered from any source + distribution. diff --git a/README b/README new file mode 100644 index 0000000..4fc1e95 --- /dev/null +++ b/README @@ -0,0 +1,70 @@ +Preparing the HTML embed +------------------------ +If your handle on mastodon is @superman@fortitude.fortress the remote +follow portal page is this: + +https://fortitude.fortress/users/superman/remote_follow + +In the following HTML snippet to embed on your site replace {uri} with +your remote_follow link corresponding to what was just explained. + +
+ + + +
+ +Next decide on the icon you want to use: + mastodon-follow-dark-da.svg + mastodon-follow-dark-en.svg + mastodon-follow-dark.svg + mastodon-follow-light-da.svg + mastodon-follow-light-en.svg + mastodon-follow-light.svg + +This is the icon you upload to somewhere on your site. Replace {icon} +with the path to your icon in the above HTML snippet. + +You can adjust the image size in the style attribute as appropriate for +your site. + +Insert the HTML snippet in the place where you want the button on your +page. + +I have prepared variants of the script to match the icons. Pick the +appropriate one and upload it to your site. Replace {script} in the +snippet below and insert it in the of your website. + + + +IMPORTANT: Remember to change the account and portal settings to point +to your mastodon account. + +You can change the link that "Create account" points to in the +create_url setting and easily translate the strings to other languages. + +Implementation notes +-------------------- +The script reserves the following globals: + +HTML/CSS: + #mastodonfollow + input[name="mastodon-handle"] + .mastodon-follow-container + .mastodon-follow-title + .mastodon-follow-input + .mastodon-follow-button +JS: + var mastodon_follow_settings + var mastodon_follow_strings + var mastodon_follow_container + function mastodon_follow_create_style + function mastodon_follow_go + function mastodon_follow_lookup + function mastodon_follow_show + +Bugs +---- +Report bugs to smpl@slamkode.ml + +License: Zlib diff --git a/mastodon-follow-dark-da.js b/mastodon-follow-dark-da.js new file mode 100644 index 0000000..77e96db --- /dev/null +++ b/mastodon-follow-dark-da.js @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: Zlib + Copyright (C) 2022 smpl */ + +var mastodon_follow_settings = { + "account": "superman@fortitude.fortress", + "portal": "https://fortitude.fortress/users/superman/remote_follow", + "dialog": { + "width": "256px", + "background": "#282c37", + "color": "#9baec8", + "title": "#fff", + "input": { + "bordercolor": "#0a0b0e", + "background": "#131419", + "color": "#fff", + "placeholder": "#c83737" + }, + "button": { + "background": "#2b90d9", + "color": "#fff" + } + } +}; +var mastodon_follow_strings = +{ + "title": "Tast dit Mastodon id", + "button": "Følg", + "create": "Opret konto", + "create_url": "https://joinmastodon.org/communities", + "error": { "handle": "Forkert id" } +}; + +var mastodon_follow_container = null; + +/* Remove nojs fallback link, when JS enabled. */ +window.addEventListener("load", function(e) { + mastodonfollow.style.cursor = "pointer"; + var a = mastodonfollow.parentNode; + var c = a.parentNode; + c.appendChild(mastodonfollow); + a.remove(); +}); + +function mastodon_follow_create_style() +{ + var style = document.createElement('style'); + var d = mastodon_follow_settings.dialog; + style.innerHTML = + ".mastodon-follow-container {" + + "display: block;" + + "z-index: 1;" + + "border: 0;" + + "border-radius: 5px;" + + "background: " + d.background + ";" + + "position: absolute;" + + "top:110%;" + + "left: 0;" + + "width: " + d.width + ";" + + 'font-family: "Roboto",Roboto,sans-serif;' + + "margin: 0 auto;" + + "padding: 20px;" + + "font-weight: 400;" + + "font-size: 13px;" + + "color: " + d.color + ";" + + "line-height: 18px;" + + "}" + + ".mastodon-follow-title {" + + "text-align: center;" + + "font-size: 18px;" + + "font-weight: 500;" + + "margin: 0;" + + "color: " + d.title + ";" + + "}" + + ".mastodon-follow-input {" + + "border: 0;" + + "border-radius: 4px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.input.background + ";" + + "width: 100%;" + + "box-sizing: border-box;" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.input.color + ";" + + "}" + + ".mastodon-follow-input::placeholder {" + + "color: " + d.input.placeholder + ";" + + "}" + + ".mastodon-follow-button {" + + "display: block;" + + "width: 100%;" + + "border: 0;" + + "border-radius: 4px;" + + "margin-right: 10px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.button.background + ";" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.button.color + ";" + + "line-height: inherit;" + + "text-align: center;" + + "text-transform: uppercase;" + + "box-sizing: border-box;" + + "cursor: pointer;" + + "}"; + document.head.appendChild(style); +} + +/* Called when request to instance is complete. + * Parse the JSON response and find the subscribe uri. + * On error goes to the instances remote_follow url. */ +function mastodon_follow_go(event) +{ + var data; + + if (this.readyState === this.DONE) { + if (this.status === 200) { + try { + data = JSON.parse(this.responseText); + } catch { + window.location = mastodon_follow_settings.portal; + return; + } + + data.links.forEach( function(e) { + if(e.rel === "http://ostatus.org/schema/1.0/subscribe") { + window.location = e.template.replace('{uri}', encodeURIComponent(mastodon_follow_settings.account)); + return; + } + }); + } + } + window.location = mastodon_follow_settings.portal; + return; +} + +/* Called when user click on follow button in dialog. + * Grab the mastodon handle from the input field and request the + * appropriate webfinger document from the users instance. + * Response is handled by mastodon_follow_go(). */ +function mastodon_follow_lookup(event) +{ + var handle_element = document.querySelector('input[name="mastodon-handle"]'); + var handle = handle_element.value; + + // remove any initial @ + if(handle.charAt(0) == '@') { + handle = handle.substring(1); + } + + // split into nick and host + var uriparts = handle.split('@'); + if(uriparts.length < 2) { + handle_element.value = ''; + handle_element.setAttribute('placeholder', mastodon_follow_strings.error.handle); + return; + } + + var oReq = new XMLHttpRequest(); + oReq.addEventListener("load", mastodon_follow_go); + oReq.open("GET", "https://" + uriparts[1] + "/.well-known/webfinger?resource=acct:" + encodeURIComponent(handle)); + oReq.send(); +} + +/* Activated when icon is clicked. + * Create the follow dialog on first run, toggle visibility on further + * clicks. */ +function mastodon_follow_show() +{ + if(!mastodon_follow_container) { + mastodon_follow_create_style(); + + mastodon_follow_container = document.createElement('div'); + mastodon_follow_container.setAttribute('class', 'mastodon-follow-container'); + + var mastodon_title = document.createElement('p'); + mastodon_title.setAttribute('class', 'mastodon-follow-title'); + mastodon_title.innerHTML = mastodon_follow_strings.title; + + var mastodon_follow_handle = document.createElement('input'); + mastodon_follow_handle.setAttribute('name', 'mastodon-handle'); + mastodon_follow_handle.setAttribute('type', 'text'); + mastodon_follow_handle.setAttribute('class', 'mastodon-follow-input'); + + var mastodon_follow_follow = document.createElement('button'); + mastodon_follow_follow.innerHTML = mastodon_follow_strings.button; + mastodon_follow_follow.setAttribute('class', 'mastodon-follow-button'); + mastodon_follow_follow.addEventListener('click', mastodon_follow_lookup); + + var createaccount = document.createElement('div'); + createaccount.style = "text-align: right;"; + var createaccount_a = document.createElement('a'); + createaccount_a.setAttribute('href', mastodon_follow_strings.create_url); + createaccount_a.innerHTML = mastodon_follow_strings.create; + createaccount.appendChild(createaccount_a); + + mastodon_follow_container.appendChild(mastodon_title); + mastodon_follow_container.appendChild(mastodon_follow_handle); + mastodon_follow_container.appendChild(mastodon_follow_follow); + mastodon_follow_container.appendChild(createaccount); + + mastodonfollow.parentElement.appendChild(mastodon_follow_container); + } else { + mastodon_follow_container.style.display = + mastodon_follow_container.style.display == "none" ? "block" : "none"; + } +} diff --git a/mastodon-follow-dark-da.svg b/mastodon-follow-dark-da.svg new file mode 100644 index 0000000..970cf5a --- /dev/null +++ b/mastodon-follow-dark-da.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/mastodon-follow-dark-en.js b/mastodon-follow-dark-en.js new file mode 100644 index 0000000..c32b194 --- /dev/null +++ b/mastodon-follow-dark-en.js @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: Zlib + Copyright (C) 2022 smpl */ + +var mastodon_follow_settings = { + "account": "superman@fortitude.fortress", + "portal": "https://fortitude.fortress/users/superman/remote_follow", + "dialog": { + "width": "256px", + "background": "#282c37", + "color": "#9baec8", + "title": "#fff", + "input": { + "bordercolor": "#0a0b0e", + "background": "#131419", + "color": "#fff", + "placeholder": "#c83737" + }, + "button": { + "background": "#2b90d9", + "color": "#fff" + } + } +}; +var mastodon_follow_strings = +{ + "title": "Enter your Mastodon handle", + "button": "Follow", + "create": "Create account", + "create_url": "https://joinmastodon.org/communities", + "error": { "handle": "Invalid handle" } +}; + +var mastodon_follow_container = null; + +/* Remove nojs fallback link, when JS enabled. */ +window.addEventListener("load", function(e) { + mastodonfollow.style.cursor = "pointer"; + var a = mastodonfollow.parentNode; + var c = a.parentNode; + c.appendChild(mastodonfollow); + a.remove(); +}); + +function mastodon_follow_create_style() +{ + var style = document.createElement('style'); + var d = mastodon_follow_settings.dialog; + style.innerHTML = + ".mastodon-follow-container {" + + "display: block;" + + "z-index: 1;" + + "border: 0;" + + "border-radius: 5px;" + + "background: " + d.background + ";" + + "position: absolute;" + + "top:110%;" + + "left: 0;" + + "width: " + d.width + ";" + + 'font-family: "Roboto",Roboto,sans-serif;' + + "margin: 0 auto;" + + "padding: 20px;" + + "font-weight: 400;" + + "font-size: 13px;" + + "color: " + d.color + ";" + + "line-height: 18px;" + + "}" + + ".mastodon-follow-title {" + + "text-align: center;" + + "font-size: 18px;" + + "font-weight: 500;" + + "margin: 0;" + + "color: " + d.title + ";" + + "}" + + ".mastodon-follow-input {" + + "border: 0;" + + "border-radius: 4px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.input.background + ";" + + "width: 100%;" + + "box-sizing: border-box;" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.input.color + ";" + + "}" + + ".mastodon-follow-input::placeholder {" + + "color: " + d.input.placeholder + ";" + + "}" + + ".mastodon-follow-button {" + + "display: block;" + + "width: 100%;" + + "border: 0;" + + "border-radius: 4px;" + + "margin-right: 10px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.button.background + ";" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.button.color + ";" + + "line-height: inherit;" + + "text-align: center;" + + "text-transform: uppercase;" + + "box-sizing: border-box;" + + "cursor: pointer;" + + "}"; + document.head.appendChild(style); +} + +/* Called when request to instance is complete. + * Parse the JSON response and find the subscribe uri. + * On error goes to the instances remote_follow url. */ +function mastodon_follow_go(event) +{ + var data; + + if (this.readyState === this.DONE) { + if (this.status === 200) { + try { + data = JSON.parse(this.responseText); + } catch { + window.location = mastodon_follow_settings.portal; + return; + } + + data.links.forEach( function(e) { + if(e.rel === "http://ostatus.org/schema/1.0/subscribe") { + window.location = e.template.replace('{uri}', encodeURIComponent(mastodon_follow_settings.account)); + return; + } + }); + } + } + window.location = mastodon_follow_settings.portal; + return; +} + +/* Called when user click on follow button in dialog. + * Grab the mastodon handle from the input field and request the + * appropriate webfinger document from the users instance. + * Response is handled by mastodon_follow_go(). */ +function mastodon_follow_lookup(event) +{ + var handle_element = document.querySelector('input[name="mastodon-handle"]'); + var handle = handle_element.value; + + // remove any initial @ + if(handle.charAt(0) == '@') { + handle = handle.substring(1); + } + + // split into nick and host + var uriparts = handle.split('@'); + if(uriparts.length < 2) { + handle_element.value = ''; + handle_element.setAttribute('placeholder', mastodon_follow_strings.error.handle); + return; + } + + var oReq = new XMLHttpRequest(); + oReq.addEventListener("load", mastodon_follow_go); + oReq.open("GET", "https://" + uriparts[1] + "/.well-known/webfinger?resource=acct:" + encodeURIComponent(handle)); + oReq.send(); +} + +/* Activated when icon is clicked. + * Create the follow dialog on first run, toggle visibility on further + * clicks. */ +function mastodon_follow_show() +{ + if(!mastodon_follow_container) { + mastodon_follow_create_style(); + + mastodon_follow_container = document.createElement('div'); + mastodon_follow_container.setAttribute('class', 'mastodon-follow-container'); + + var mastodon_title = document.createElement('p'); + mastodon_title.setAttribute('class', 'mastodon-follow-title'); + mastodon_title.innerHTML = mastodon_follow_strings.title; + + var mastodon_follow_handle = document.createElement('input'); + mastodon_follow_handle.setAttribute('name', 'mastodon-handle'); + mastodon_follow_handle.setAttribute('type', 'text'); + mastodon_follow_handle.setAttribute('class', 'mastodon-follow-input'); + + var mastodon_follow_follow = document.createElement('button'); + mastodon_follow_follow.innerHTML = mastodon_follow_strings.button; + mastodon_follow_follow.setAttribute('class', 'mastodon-follow-button'); + mastodon_follow_follow.addEventListener('click', mastodon_follow_lookup); + + var createaccount = document.createElement('div'); + createaccount.style = "text-align: right;"; + var createaccount_a = document.createElement('a'); + createaccount_a.setAttribute('href', mastodon_follow_strings.create_url); + createaccount_a.innerHTML = mastodon_follow_strings.create; + createaccount.appendChild(createaccount_a); + + mastodon_follow_container.appendChild(mastodon_title); + mastodon_follow_container.appendChild(mastodon_follow_handle); + mastodon_follow_container.appendChild(mastodon_follow_follow); + mastodon_follow_container.appendChild(createaccount); + + mastodonfollow.parentElement.appendChild(mastodon_follow_container); + } else { + mastodon_follow_container.style.display = + mastodon_follow_container.style.display == "none" ? "block" : "none"; + } +} diff --git a/mastodon-follow-dark-en.svg b/mastodon-follow-dark-en.svg new file mode 100644 index 0000000..1269bfc --- /dev/null +++ b/mastodon-follow-dark-en.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + diff --git a/mastodon-follow-dark.svg b/mastodon-follow-dark.svg new file mode 100644 index 0000000..43b9316 --- /dev/null +++ b/mastodon-follow-dark.svg @@ -0,0 +1,24 @@ + + + + + + + diff --git a/mastodon-follow-light-da.js b/mastodon-follow-light-da.js new file mode 100644 index 0000000..e0c4060 --- /dev/null +++ b/mastodon-follow-light-da.js @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: Zlib + Copyright (C) 2022 smpl */ + +var mastodon_follow_settings = { + "account": "superman@fortitude.fortress", + "portal": "https://fortitude.fortress/users/superman/remote_follow", + "dialog": { + "width": "256px", + "background": "#d9e1e8", + "color": "#282c37", + "title": "#282c37", + "input": { + "bordercolor": "#b3c3d1", + "background": "#f9fafb", + "color": "#000", + "placeholder": "#c83737" + }, + "button": { + "background": "#2b90d9", + "color": "#fff" + } + } +}; +var mastodon_follow_strings = +{ + "title": "Tast dit Mastodon id", + "button": "Følg", + "create": "Opret konto", + "create_url": "https://joinmastodon.org/communities", + "error": { "handle": "Forkert id" } +}; + +var mastodon_follow_container = null; + +/* Remove nojs fallback link, when JS enabled. */ +window.addEventListener("load", function(e) { + mastodonfollow.style.cursor = "pointer"; + var a = mastodonfollow.parentNode; + var c = a.parentNode; + c.appendChild(mastodonfollow); + a.remove(); +}); + +function mastodon_follow_create_style() +{ + var style = document.createElement('style'); + var d = mastodon_follow_settings.dialog; + style.innerHTML = + ".mastodon-follow-container {" + + "display: block;" + + "z-index: 1;" + + "border: 0;" + + "border-radius: 5px;" + + "background: " + d.background + ";" + + "position: absolute;" + + "top:110%;" + + "left: 0;" + + "width: " + d.width + ";" + + 'font-family: "Roboto",Roboto,sans-serif;' + + "margin: 0 auto;" + + "padding: 20px;" + + "font-weight: 400;" + + "font-size: 13px;" + + "color: " + d.color + ";" + + "line-height: 18px;" + + "}" + + ".mastodon-follow-title {" + + "text-align: center;" + + "font-size: 18px;" + + "font-weight: 500;" + + "margin: 0;" + + "color: " + d.title + ";" + + "}" + + ".mastodon-follow-input {" + + "border: 0;" + + "border-radius: 4px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.input.background + ";" + + "width: 100%;" + + "box-sizing: border-box;" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.input.color + ";" + + "}" + + ".mastodon-follow-input::placeholder {" + + "color: " + d.input.placeholder + ";" + + "}" + + ".mastodon-follow-button {" + + "display: block;" + + "width: 100%;" + + "border: 0;" + + "border-radius: 4px;" + + "margin-right: 10px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.button.background + ";" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.button.color + ";" + + "line-height: inherit;" + + "text-align: center;" + + "text-transform: uppercase;" + + "box-sizing: border-box;" + + "cursor: pointer;" + + "}"; + document.head.appendChild(style); +} + +/* Called when request to instance is complete. + * Parse the JSON response and find the subscribe uri. + * On error goes to the instances remote_follow url. */ +function mastodon_follow_go(event) +{ + var data; + + if (this.readyState === this.DONE) { + if (this.status === 200) { + try { + data = JSON.parse(this.responseText); + } catch { + window.location = mastodon_follow_settings.portal; + return; + } + + data.links.forEach( function(e) { + if(e.rel === "http://ostatus.org/schema/1.0/subscribe") { + window.location = e.template.replace('{uri}', encodeURIComponent(mastodon_follow_settings.account)); + return; + } + }); + } + } + window.location = mastodon_follow_settings.portal; + return; +} + +/* Called when user click on follow button in dialog. + * Grab the mastodon handle from the input field and request the + * appropriate webfinger document from the users instance. + * Response is handled by mastodon_follow_go(). */ +function mastodon_follow_lookup(event) +{ + var handle_element = document.querySelector('input[name="mastodon-handle"]'); + var handle = handle_element.value; + + // remove any initial @ + if(handle.charAt(0) == '@') { + handle = handle.substring(1); + } + + // split into nick and host + var uriparts = handle.split('@'); + if(uriparts.length < 2) { + handle_element.value = ''; + handle_element.setAttribute('placeholder', mastodon_follow_strings.error.handle); + return; + } + + var oReq = new XMLHttpRequest(); + oReq.addEventListener("load", mastodon_follow_go); + oReq.open("GET", "https://" + uriparts[1] + "/.well-known/webfinger?resource=acct:" + encodeURIComponent(handle)); + oReq.send(); +} + +/* Activated when icon is clicked. + * Create the follow dialog on first run, toggle visibility on further + * clicks. */ +function mastodon_follow_show() +{ + if(!mastodon_follow_container) { + mastodon_follow_create_style(); + + mastodon_follow_container = document.createElement('div'); + mastodon_follow_container.setAttribute('class', 'mastodon-follow-container'); + + var mastodon_title = document.createElement('p'); + mastodon_title.setAttribute('class', 'mastodon-follow-title'); + mastodon_title.innerHTML = mastodon_follow_strings.title; + + var mastodon_follow_handle = document.createElement('input'); + mastodon_follow_handle.setAttribute('name', 'mastodon-handle'); + mastodon_follow_handle.setAttribute('type', 'text'); + mastodon_follow_handle.setAttribute('class', 'mastodon-follow-input'); + + var mastodon_follow_follow = document.createElement('button'); + mastodon_follow_follow.innerHTML = mastodon_follow_strings.button; + mastodon_follow_follow.setAttribute('class', 'mastodon-follow-button'); + mastodon_follow_follow.addEventListener('click', mastodon_follow_lookup); + + var createaccount = document.createElement('div'); + createaccount.style = "text-align: right;"; + var createaccount_a = document.createElement('a'); + createaccount_a.setAttribute('href', mastodon_follow_strings.create_url); + createaccount_a.innerHTML = mastodon_follow_strings.create; + createaccount.appendChild(createaccount_a); + + mastodon_follow_container.appendChild(mastodon_title); + mastodon_follow_container.appendChild(mastodon_follow_handle); + mastodon_follow_container.appendChild(mastodon_follow_follow); + mastodon_follow_container.appendChild(createaccount); + + mastodonfollow.parentElement.appendChild(mastodon_follow_container); + } else { + mastodon_follow_container.style.display = + mastodon_follow_container.style.display == "none" ? "block" : "none"; + } +} diff --git a/mastodon-follow-light-da.svg b/mastodon-follow-light-da.svg new file mode 100644 index 0000000..99f2acb --- /dev/null +++ b/mastodon-follow-light-da.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/mastodon-follow-light-en.js b/mastodon-follow-light-en.js new file mode 100644 index 0000000..39d2979 --- /dev/null +++ b/mastodon-follow-light-en.js @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: Zlib + Copyright (C) 2022 smpl */ + +var mastodon_follow_settings = { + "account": "superman@fortitude.fortress", + "portal": "https://fortitude.fortress/users/superman/remote_follow", + "dialog": { + "width": "256px", + "background": "#d9e1e8", + "color": "#282c37", + "title": "#282c37", + "input": { + "bordercolor": "#b3c3d1", + "background": "#f9fafb", + "color": "#000", + "placeholder": "#c83737" + }, + "button": { + "background": "#2b90d9", + "color": "#fff" + } + } +}; +var mastodon_follow_strings = +{ + "title": "Enter your Mastodon handle", + "button": "Follow", + "create": "Create account", + "create_url": "https://joinmastodon.org/communities", + "error": { "handle": "Invalid handle" } +}; + +var mastodon_follow_container = null; + +/* Remove nojs fallback link, when JS enabled. */ +window.addEventListener("load", function(e) { + mastodonfollow.style.cursor = "pointer"; + var a = mastodonfollow.parentNode; + var c = a.parentNode; + c.appendChild(mastodonfollow); + a.remove(); +}); + +function mastodon_follow_create_style() +{ + var style = document.createElement('style'); + var d = mastodon_follow_settings.dialog; + style.innerHTML = + ".mastodon-follow-container {" + + "display: block;" + + "z-index: 1;" + + "border: 0;" + + "border-radius: 5px;" + + "background: " + d.background + ";" + + "position: absolute;" + + "top:110%;" + + "left: 0;" + + "width: " + d.width + ";" + + 'font-family: "Roboto",Roboto,sans-serif;' + + "margin: 0 auto;" + + "padding: 20px;" + + "font-weight: 400;" + + "font-size: 13px;" + + "color: " + d.color + ";" + + "line-height: 18px;" + + "}" + + ".mastodon-follow-title {" + + "text-align: center;" + + "font-size: 18px;" + + "font-weight: 500;" + + "margin: 0;" + + "color: " + d.title + ";" + + "}" + + ".mastodon-follow-input {" + + "border: 0;" + + "border-radius: 4px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.input.background + ";" + + "width: 100%;" + + "box-sizing: border-box;" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.input.color + ";" + + "}" + + ".mastodon-follow-input::placeholder {" + + "color: " + d.input.placeholder + ";" + + "}" + + ".mastodon-follow-button {" + + "display: block;" + + "width: 100%;" + + "border: 0;" + + "border-radius: 4px;" + + "margin-right: 10px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.button.background + ";" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.button.color + ";" + + "line-height: inherit;" + + "text-align: center;" + + "text-transform: uppercase;" + + "box-sizing: border-box;" + + "cursor: pointer;" + + "}"; + document.head.appendChild(style); +} + +/* Called when request to instance is complete. + * Parse the JSON response and find the subscribe uri. + * On error goes to the instances remote_follow url. */ +function mastodon_follow_go(event) +{ + var data; + + if (this.readyState === this.DONE) { + if (this.status === 200) { + try { + data = JSON.parse(this.responseText); + } catch { + window.location = mastodon_follow_settings.portal; + return; + } + + data.links.forEach( function(e) { + if(e.rel === "http://ostatus.org/schema/1.0/subscribe") { + window.location = e.template.replace('{uri}', encodeURIComponent(mastodon_follow_settings.account)); + return; + } + }); + } + } + window.location = mastodon_follow_settings.portal; + return; +} + +/* Called when user click on follow button in dialog. + * Grab the mastodon handle from the input field and request the + * appropriate webfinger document from the users instance. + * Response is handled by mastodon_follow_go(). */ +function mastodon_follow_lookup(event) +{ + var handle_element = document.querySelector('input[name="mastodon-handle"]'); + var handle = handle_element.value; + + // remove any initial @ + if(handle.charAt(0) == '@') { + handle = handle.substring(1); + } + + // split into nick and host + var uriparts = handle.split('@'); + if(uriparts.length < 2) { + handle_element.value = ''; + handle_element.setAttribute('placeholder', mastodon_follow_strings.error.handle); + return; + } + + var oReq = new XMLHttpRequest(); + oReq.addEventListener("load", mastodon_follow_go); + oReq.open("GET", "https://" + uriparts[1] + "/.well-known/webfinger?resource=acct:" + encodeURIComponent(handle)); + oReq.send(); +} + +/* Activated when icon is clicked. + * Create the follow dialog on first run, toggle visibility on further + * clicks. */ +function mastodon_follow_show() +{ + if(!mastodon_follow_container) { + mastodon_follow_create_style(); + + mastodon_follow_container = document.createElement('div'); + mastodon_follow_container.setAttribute('class', 'mastodon-follow-container'); + + var mastodon_title = document.createElement('p'); + mastodon_title.setAttribute('class', 'mastodon-follow-title'); + mastodon_title.innerHTML = mastodon_follow_strings.title; + + var mastodon_follow_handle = document.createElement('input'); + mastodon_follow_handle.setAttribute('name', 'mastodon-handle'); + mastodon_follow_handle.setAttribute('type', 'text'); + mastodon_follow_handle.setAttribute('class', 'mastodon-follow-input'); + + var mastodon_follow_follow = document.createElement('button'); + mastodon_follow_follow.innerHTML = mastodon_follow_strings.button; + mastodon_follow_follow.setAttribute('class', 'mastodon-follow-button'); + mastodon_follow_follow.addEventListener('click', mastodon_follow_lookup); + + var createaccount = document.createElement('div'); + createaccount.style = "text-align: right;"; + var createaccount_a = document.createElement('a'); + createaccount_a.setAttribute('href', mastodon_follow_strings.create_url); + createaccount_a.innerHTML = mastodon_follow_strings.create; + createaccount.appendChild(createaccount_a); + + mastodon_follow_container.appendChild(mastodon_title); + mastodon_follow_container.appendChild(mastodon_follow_handle); + mastodon_follow_container.appendChild(mastodon_follow_follow); + mastodon_follow_container.appendChild(createaccount); + + mastodonfollow.parentElement.appendChild(mastodon_follow_container); + } else { + mastodon_follow_container.style.display = + mastodon_follow_container.style.display == "none" ? "block" : "none"; + } +} diff --git a/mastodon-follow-light-en.svg b/mastodon-follow-light-en.svg new file mode 100644 index 0000000..6aaeba7 --- /dev/null +++ b/mastodon-follow-light-en.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + diff --git a/mastodon-follow-light.svg b/mastodon-follow-light.svg new file mode 100644 index 0000000..eb32a59 --- /dev/null +++ b/mastodon-follow-light.svg @@ -0,0 +1,24 @@ + + + + + + + diff --git a/mastodon-follow.js b/mastodon-follow.js new file mode 100644 index 0000000..a7c6989 --- /dev/null +++ b/mastodon-follow.js @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: Zlib + Copyright (C) 2022 smpl */ + +///* Light theme matching mastodon-follow-light.svg +var mastodon_follow_settings = { + "account": "superman@fortitude.fortress", + "portal": "https://fortitude.fortress/users/superman/remote_follow", + "dialog": { + "width": "256px", + "background": "#d9e1e8", + "color": "#282c37", + "title": "#282c37", + "input": { + "bordercolor": "#b3c3d1", + "background": "#f9fafb", + "color": "#000", + "placeholder": "#c83737" + }, + "button": { + "background": "#2b90d9", + "color": "#fff" + } + } +};//*/ +///* +var mastodon_follow_strings = +{ + "title": "Enter your Mastodon handle", + "button": "Follow", + "create": "Create account", + "create_url": "https://joinmastodon.org/communities", + "error": { "handle": "Invalid handle" } +};//*/ +/* Dark theme matching mastodon-follow-dark.svg +var mastodon_follow_settings = { + "account": "superman@fortitude.fortress", + "portal": "https://fortitude.fortress/users/superman/remote_follow", + "dialog": { + "width": "256px", + "background": "#282c37", + "color": "#9baec8", + "title": "#fff", + "input": { + "bordercolor": "#0a0b0e", + "background": "#131419", + "color": "#fff", + "placeholder": "#c83737" + }, + "button": { + "background": "#2b90d9", + "color": "#fff" + } + } +};//*/ +/* +var mastodon_follow_strings = +{ + "title": "Tast dit Mastodon id", + "button": "Følg", + "create": "Opret konto", + "create_url": "https://joinmastodon.org/communities", + "error": { "handle": "Forkert id" } +};//*/ + +var mastodon_follow_container = null; + +/* Remove nojs fallback link, when JS enabled. */ +window.addEventListener("load", function(e) { + mastodonfollow.style.cursor = "pointer"; + var a = mastodonfollow.parentNode; + var c = a.parentNode; + c.appendChild(mastodonfollow); + a.remove(); +}); + +function mastodon_follow_create_style() +{ + var style = document.createElement('style'); + var d = mastodon_follow_settings.dialog; + style.innerHTML = + ".mastodon-follow-container {" + + "display: block;" + + "z-index: 1;" + + "border: 0;" + + "border-radius: 5px;" + + "background: " + d.background + ";" + + "position: absolute;" + + "top:110%;" + + "left: 0;" + + "width: " + d.width + ";" + + 'font-family: "Roboto",Roboto,sans-serif;' + + "margin: 0 auto;" + + "padding: 20px;" + + "font-weight: 400;" + + "font-size: 13px;" + + "color: " + d.color + ";" + + "line-height: 18px;" + + "}" + + ".mastodon-follow-title {" + + "text-align: center;" + + "font-size: 18px;" + + "font-weight: 500;" + + "margin: 0;" + + "color: " + d.title + ";" + + "}" + + ".mastodon-follow-input {" + + "border: 0;" + + "border-radius: 4px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.input.background + ";" + + "width: 100%;" + + "box-sizing: border-box;" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.input.color + ";" + + "}" + + ".mastodon-follow-input::placeholder {" + + "color: " + d.input.placeholder + ";" + + "}" + + ".mastodon-follow-button {" + + "display: block;" + + "width: 100%;" + + "border: 0;" + + "border-radius: 4px;" + + "margin-right: 10px;" + + "margin-top: 20px;" + + "padding: 10px;" + + "background: " + d.button.background + ";" + + "font-family: inherit;" + + "font-weight: 500;" + + "font-size: 18px;" + + "color: " + d.button.color + ";" + + "line-height: inherit;" + + "text-align: center;" + + "text-transform: uppercase;" + + "box-sizing: border-box;" + + "cursor: pointer;" + + "}"; + document.head.appendChild(style); +} + +/* Called when request to instance is complete. + * Parse the JSON response and find the subscribe uri. + * On error goes to the instances remote_follow url. */ +function mastodon_follow_go(event) +{ + var data; + + if (this.readyState === this.DONE) { + if (this.status === 200) { + try { + data = JSON.parse(this.responseText); + } catch { + window.location = mastodon_follow_settings.portal; + return; + } + + data.links.forEach( function(e) { + if(e.rel === "http://ostatus.org/schema/1.0/subscribe") { + window.location = e.template.replace('{uri}', encodeURIComponent(mastodon_follow_settings.account)); + return; + } + }); + } + } + window.location = mastodon_follow_settings.portal; + return; +} + +/* Called when user click on follow button in dialog. + * Grab the mastodon handle from the input field and request the + * appropriate webfinger document from the users instance. + * Response is handled by mastodon_follow_go(). */ +function mastodon_follow_lookup(event) +{ + var handle_element = document.querySelector('input[name="mastodon-handle"]'); + var handle = handle_element.value; + + // remove any initial @ + if(handle.charAt(0) == '@') { + handle = handle.substring(1); + } + + // split into nick and host + var uriparts = handle.split('@'); + if(uriparts.length < 2) { + handle_element.value = ''; + handle_element.setAttribute('placeholder', mastodon_follow_strings.error.handle); + return; + } + + var oReq = new XMLHttpRequest(); + oReq.addEventListener("load", mastodon_follow_go); + oReq.open("GET", "https://" + uriparts[1] + "/.well-known/webfinger?resource=acct:" + encodeURIComponent(handle)); + oReq.send(); +} + +/* Activated when icon is clicked. + * Create the follow dialog on first run, toggle visibility on further + * clicks. */ +function mastodon_follow_show() +{ + if(!mastodon_follow_container) { + mastodon_follow_create_style(); + + mastodon_follow_container = document.createElement('div'); + mastodon_follow_container.setAttribute('class', 'mastodon-follow-container'); + + var mastodon_title = document.createElement('p'); + mastodon_title.setAttribute('class', 'mastodon-follow-title'); + mastodon_title.innerHTML = mastodon_follow_strings.title; + + var mastodon_follow_handle = document.createElement('input'); + mastodon_follow_handle.setAttribute('name', 'mastodon-handle'); + mastodon_follow_handle.setAttribute('type', 'text'); + mastodon_follow_handle.setAttribute('class', 'mastodon-follow-input'); + + var mastodon_follow_follow = document.createElement('button'); + mastodon_follow_follow.innerHTML = mastodon_follow_strings.button; + mastodon_follow_follow.setAttribute('class', 'mastodon-follow-button'); + mastodon_follow_follow.addEventListener('click', mastodon_follow_lookup); + + var createaccount = document.createElement('div'); + createaccount.style = "text-align: right;"; + var createaccount_a = document.createElement('a'); + createaccount_a.setAttribute('href', mastodon_follow_strings.create_url); + createaccount_a.innerHTML = mastodon_follow_strings.create; + createaccount.appendChild(createaccount_a); + + mastodon_follow_container.appendChild(mastodon_title); + mastodon_follow_container.appendChild(mastodon_follow_handle); + mastodon_follow_container.appendChild(mastodon_follow_follow); + mastodon_follow_container.appendChild(createaccount); + + mastodonfollow.parentElement.appendChild(mastodon_follow_container); + } else { + mastodon_follow_container.style.display = + mastodon_follow_container.style.display == "none" ? "block" : "none"; + } +}