FEATURE: optional quote sharing buttons (#10254)

FEATURE: optional quote sharing buttons (#10254)

diff --git a/app/assets/javascripts/discourse/app/components/quote-button.js b/app/assets/javascripts/discourse/app/components/quote-button.js
index 2b932be..1672857 100644
--- a/app/assets/javascripts/discourse/app/components/quote-button.js
+++ b/app/assets/javascripts/discourse/app/components/quote-button.js
@@ -2,8 +2,16 @@ import { schedule } from "@ember/runloop";
 import Component from "@ember/component";
 import discourseDebounce from "discourse/lib/debounce";
 import toMarkdown from "discourse/lib/to-markdown";
-import { selectedText, selectedElement } from "discourse/lib/utilities";
+import {
+  selectedText,
+  selectedElement,
+  postUrl
+} from "discourse/lib/utilities";
+import { getAbsoluteURL } from "discourse-common/lib/get-url";
 import { INPUT_DELAY } from "discourse-common/config/environment";
+import { action } from "@ember/object";
+import discourseComputed from "discourse-common/utils/decorators";
+import Sharing from "discourse/lib/sharing";
 
 function getQuoteTitle(element) {
   const titleEl = element.querySelector(".title");
@@ -201,8 +209,59 @@ export default Component.extend({
       .off("selectionchange.quote-button");
   },
 
-  click() {
+  @discourseComputed
+  quoteSharingEnabled() {
+    if (
+      this.site.mobileView ||
+      this.siteSettings.share_quote_visibility === "none" ||
+      this.quoteSharingSources.length === 0 ||
+      (this.currentUser &&
+        this.siteSettings.share_quote_visibility === "anonymous")
+    ) {
+      return false;
+    }
+
+    return true;
+  },
+
+  @discourseComputed("topic.isPrivateMessage")
+  quoteSharingSources(isPM) {
+    return Sharing.activeSources(
+      this.siteSettings.share_quote_buttons,
+      this.siteSettings.login_required || isPM
+    );
+  },
+
+  @discourseComputed
+  quoteSharingShowLabel() {
+    return this.quoteSharingSources.length > 1;
+  },
+
+  @discourseComputed("topic.{id,slug}", "quoteState")
+  shareUrl(topic, quoteState) {
+    return getAbsoluteURL(postUrl(topic.slug, topic.id, quoteState.postId));
+  },
+
+  @discourseComputed("topic.details.can_create_post", "composer.visible")
+  embedQuoteButton(canCreatePost, composerOpened) {
+    return (
+      (canCreatePost || composerOpened) &&
+      this.currentUser &&
+      this.currentUser.get("enable_quoting")
+    );
+  },
+
+  @action
+  insertQuote() {
     this.attrs.selectText().then(() => this._hideButton());
-    return false;
+  },
+
+  @action
+  share(source) {
+    Sharing.shareSource(source, {
+      url: this.shareUrl,
+      title: this.topic.title,
+      quote: window.getSelection().toString()
+    });
   }
 });
diff --git a/app/assets/javascripts/discourse/app/controllers/topic.js b/app/assets/javascripts/discourse/app/controllers/topic.js
index eba29fa..54e69b2 100644
--- a/app/assets/javascripts/discourse/app/controllers/topic.js
+++ b/app/assets/javascripts/discourse/app/controllers/topic.js
@@ -77,15 +77,6 @@ export default Controller.extend(bufferedProperty("model"), {
     }
   },
 
-  @discourseComputed("model.details.can_create_post", "composer.visible")
-  embedQuoteButton(canCreatePost, composerOpened) {
-    return (
-      (canCreatePost || composerOpened) &&
-      this.currentUser &&
-      this.currentUser.get("enable_quoting")
-    );
-  },
-
   @discourseComputed("model.postStream.loaded", "model.category_id")
   showSharedDraftControls(loaded, categoryId) {
     let draftCat = this.site.shared_drafts_category_id;
diff --git a/app/assets/javascripts/discourse/app/initializers/sharing-sources.js b/app/assets/javascripts/discourse/app/initializers/sharing-sources.js
index 127a6e5..bb0fd89 100644
--- a/app/assets/javascripts/discourse/app/initializers/sharing-sources.js
+++ b/app/assets/javascripts/discourse/app/initializers/sharing-sources.js
@@ -4,17 +4,17 @@ import Sharing from "discourse/lib/sharing";
 export default {
   name: "sharing-sources",
 
-  initialize: function() {
+  initialize: function(container) {
+    const siteSettings = container.lookup("site-settings:main");
+
     Sharing.addSource({
       id: "twitter",
       icon: "fab-twitter-square",
-      generateUrl: function(link, title) {
-        return (
-          "http://twitter.com/intent/tweet?url=" +
-          encodeURIComponent(link) +
-          "&text=" +
-          encodeURIComponent(title)
-        );
+      generateUrl: function(link, title, quote = "") {
+        const text = quote ? `"${quote}" -- ` : title;
+        return `http://twitter.com/intent/tweet?url=${encodeURIComponent(
+          link
+        )}&text=${encodeURIComponent(text)}`;
       },
       shouldOpenInPopup: true,
       title: I18n.t("share.twitter"),
@@ -25,13 +25,14 @@ export default {
       id: "facebook",
       icon: "fab-facebook",
       title: I18n.t("share.facebook"),
-      generateUrl: function(link, title) {
-        return (
-          "http://www.facebook.com/sharer.php?u=" +
-          encodeURIComponent(link) +
-          "&t=" +
-          encodeURIComponent(title)
-        );
+      generateUrl: function(link, title, quote = "") {
+        const fb_url = siteSettings.facebook_app_id
+          ? `https://www.facebook.com/dialog/share?app_id=${
+              siteSettings.facebook_app_id
+            }&quote=${encodeURIComponent(quote)}&href=`
+          : "https://www.facebook.com/sharer.php?u=";
+
+        return `${fb_url}${encodeURIComponent(link)}`;
       },
       shouldOpenInPopup: true
     });
@@ -40,17 +41,18 @@ export default {
       id: "email",
       icon: "envelope-square",
       title: I18n.t("share.email"),
-      showInPrivateContext: true,
-      generateUrl: function(link, title) {
+      generateUrl: function(link, title, quote = "") {
+        const body = quote ? `${quote} \n\n ${link}` : link;
         return (
           "mailto:?to=&subject=" +
           encodeURIComponent(
             "[" + Discourse.SiteSettings.title + "] " + title
           ) +
           "&body=" +
-          encodeURIComponent(link)
+          encodeURIComponent(body)
         );
-      }
+      },
+      showInPrivateContext: true
     });
   }
 };
diff --git a/app/assets/javascripts/discourse/app/lib/sharing.js b/app/assets/javascripts/discourse/app/lib/sharing.js
index aa7b0a5..5c0dfe5 100644
--- a/app/assets/javascripts/discourse/app/lib/sharing.js
+++ b/app/assets/javascripts/discourse/app/lib/sharing.js
@@ -59,7 +59,7 @@ export default {
     if (source.clickHandler) {
       source.clickHandler(data.url, data.title);
     } else {
-      const url = source.generateUrl(data.url, data.title);
+      const url = source.generateUrl(data.url, data.title, data.quote);
       const options = {
         menubar: "no",
         toolbar: "no",
@@ -74,6 +74,8 @@ export default {
 
       if (source.shouldOpenInPopup) {
         window.open(url, "", stringOptions);
+      } else if (source.id === "email") {
+        window.location.href = url;
       } else {
         window.open(url, "_blank");
       }
diff --git a/app/assets/javascripts/discourse/app/templates/components/quote-button.hbs b/app/assets/javascripts/discourse/app/templates/components/quote-button.hbs
index 868baa3..a28dd8e 100644
--- a/app/assets/javascripts/discourse/app/templates/components/quote-button.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/quote-button.hbs
@@ -1 +1,31 @@
-{{d-icon "quote-left"}} <span class="quote-label">{{i18n "post.quote_reply"}}</span>
+{{#if embedQuoteButton}}
+  {{d-button
+    class="btn-flat insert-quote"
+    action=(action "insertQuote")
+    icon="quote-left"
+    label="post.quote_reply"}}
+{{/if}}
+
+{{#if quoteSharingEnabled}}
+  <span class="quote-sharing">
+    {{#if quoteSharingShowLabel}}
+      {{d-button
+        icon="share"
+        label="post.quote_share"
+        class="btn-flat quote-share-label"}}
+    {{/if}}
+
+    <span class="quote-share-buttons">
+      {{#each quoteSharingSources as |source|}}
+        {{d-button

[... diff too long, it was truncated ...]

GitHub sha: bf22f708

1 Like

This commit appears in #10254 which was approved by jjaffeux. It was merged by pmusaraj.