Refactor sharing dialog for extensibility

This commit is contained in:
Robin Ward 2015-01-13 17:26:05 -05:00
parent 0de6226a20
commit 8b87d8ac2d
11 changed files with 133 additions and 131 deletions

View File

@ -0,0 +1,9 @@
export default Ember.Component.extend({
classNameBindings: [':social-link'],
actions: {
share: function(source) {
this.sendAction('action', source);
},
}
});

View File

@ -1,7 +1,8 @@
import DiscourseController from 'discourse/controllers/controller';
import Sharing from 'discourse/lib/sharing';
export default DiscourseController.extend({
export default Ember.Controller.extend({
needs: ['topic'],
title: Ember.computed.alias('controllers.topic.title'),
displayDate: function() {
return Discourse.Formatter.longDateNoYear(new Date(this.get('date')));
@ -14,20 +15,17 @@ export default DiscourseController.extend({
return false;
},
sharePopup: function(target, url) {
window.open(url, '', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=600,height=' + Discourse.ShareLink.popupHeight(target));
return false;
share: function(source) {
var url = source.generateUrl(this.get('link'), this.get('title'));
if (source.shouldOpenInPopup) {
window.open(url, '', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=600,height=' + (source.popupHeight || 315));
} else {
window.open(url, '_blank');
}
}
},
shareLinks: function() {
return Discourse.SiteSettings.share_links.split('|').map(function(i) {
if( Discourse.ShareLink.supportedTargets.indexOf(i) >= 0 ) {
return Discourse.ShareLink.create({target: i, link: this.get('link'), topicTitle: this.get('controllers.topic.title')});
} else {
return null;
}
}, this).compact();
}.property('link')
sources: function() {
return Sharing.activeSources();
}.property()
});

View File

@ -0,0 +1,52 @@
import Sharing from 'discourse/lib/sharing';
export default {
name: 'sharing-sources',
initialize: function() {
// Backwards compatibility
Discourse.ShareLink = {};
Discourse.ShareLink.addTarget = function(id, source) {
Ember.warn('Discourse.ShareLink.addTarget is deprecated. Import `Sharing` and call `addSource` instead.');
source.id = id;
Sharing.addSource(source);
};
Sharing.addSource({
id: 'twitter',
iconClass: 'fa-twitter-square',
generateUrl: function(link, title) {
return "http://twitter.com/intent/tweet?url=" + encodeURIComponent(link) + "&text=" + encodeURIComponent(title);
},
shouldOpenInPopup: true,
popupHeight: 265
});
Sharing.addSource({
id: 'facebook',
iconClass: 'fa-facebook-square',
generateUrl: function(link, title) {
return "http://www.facebook.com/sharer.php?u=" + encodeURIComponent(link) + '&t=' + encodeURIComponent(title);
},
shouldOpenInPopup: true
});
Sharing.addSource({
id: 'google+',
iconClass: 'fa-google-plus-square',
generateUrl: function(link) {
return "https://plus.google.com/share?url=" + encodeURIComponent(link);
},
shouldOpenInPopup: true,
popupHeight: 600
});
Sharing.addSource({
id: 'email',
iconClass: 'fa-envelope-square',
generateUrl: function(link, title) {
return "mailto:?to=&subject=" + encodeURIComponent('[' + Discourse.SiteSettings.title + '] ' + title) + "&body=" + encodeURIComponent(link);
}
});
}
};

View File

@ -0,0 +1,40 @@
/**
If you want to add a new sharing source to Discourse, you can do so like this:
```javascript
import Sharing from 'discourse/lib/sharing';
Sharing.addSource({
// This id must be present in the `share_links` site setting too
id: 'twitter',
// The icon that will be displayed
iconClass: 'fa-twitter-square',
// A callback for generating the remote link from the `link` and `title`
generateUrl: function(link, title) {
return "http://twitter.com/intent/tweet?url=" + encodeURIComponent(link) + "&text=" + encodeURIComponent(title);
},
// If true, opens in a popup of `popupHeight` size. If false it's opened in a new tab
shouldOpenInPopup: true,
popupHeight: 265
});
```
**/
var _sources = [];
export default {
addSource: function (source) {
_sources.push(source);
},
activeSources: function() {
var enabled = Discourse.SiteSettings.share_links.split('|');
return _sources.filter(function(s) {
return enabled.indexOf(s.id) !== -1;
});
}
};

View File

@ -1,84 +0,0 @@
/**
A data model representing a link to share a post on a 3rd party site,
like Twitter, Facebook, and Google+.
@class ShareLink
@extends Discourse.Model
@namespace Discourse
@module Discourse
**/
Discourse.ShareLink = Discourse.Model.extend({
href: function() {
return Discourse.ShareLink.urlFor[this.get('target')](this.get('link'), this.get('topicTitle'));
}.property('target', 'link', 'topicTitle'),
title: Discourse.computed.i18n('target', 'share.%@'),
iconClass: function() {
return Discourse.ShareLink.iconClasses[this.get('target')];
}.property('target'),
openInPopup: function() {
return( Discourse.ShareLink.shouldOpenInPopup[this.get('target')] );
}.property('target')
});
Discourse.ShareLink.reopenClass({
supportedTargets: [],
urlFor: {},
iconClasses: {},
popupHeights: {},
shouldOpenInPopup: {},
addTarget: function(id, object) {
var self = this;
self.supportedTargets.push(id);
self.urlFor[id] = object.generateUrl;
self.iconClasses[id] = object.iconClass;
self.popupHeights[id] = object.popupHeight || 315;
self.shouldOpenInPopup[id] = object.shouldOpenInPopup;
},
popupHeight: function(target) {
return (this.popupHeights[target] || 315);
}
});
(function() {
Discourse.ShareLink.addTarget('twitter', {
iconClass: 'fa-twitter-square',
generateUrl: function(link, title) {
return ("http://twitter.com/intent/tweet?url=" + encodeURIComponent(link) + "&text=" + encodeURIComponent(title) );
},
shouldOpenInPopup: true,
popupHeight: 265
});
Discourse.ShareLink.addTarget('facebook', {
iconClass: 'fa-facebook-square',
generateUrl: function(link, title) {
return ("http://www.facebook.com/sharer.php?u=" + encodeURIComponent(link) + '&t=' + encodeURIComponent(title));
},
shouldOpenInPopup: true,
popupHeight: 315
});
Discourse.ShareLink.addTarget('google+', {
iconClass: 'fa-google-plus-square',
generateUrl: function(link) {
return ("https://plus.google.com/share?url=" + encodeURIComponent(link));
},
shouldOpenInPopup: true,
popupHeight: 600
});
Discourse.ShareLink.addTarget('email', {
iconClass: 'fa-envelope-square',
generateUrl: function(link, title) {
return ("mailto:?to=&subject=" + encodeURIComponent('[' + Discourse.SiteSettings.title + '] ' + title) + "&body=" + encodeURIComponent(link));
},
shouldOpenInPopup: false
});
})();

View File

@ -0,0 +1 @@
<a href {{action "share" source}} {{bind-attr title="title"}}><i {{bind-attr class=":fa source.iconClass"}}></i></a>

View File

@ -10,8 +10,11 @@
<div class="share-for-touch"><div class="overflow-ellipsis"><a></a></div></div>
</div>
{{each s in shareLinks itemView='share-link'}}
{{#each s in sources}}
{{share-source source=s title=title action="share"}}
{{/each}}
<div class='link'>
<a href {{action "close"}} title='{{i18n 'share.close'}}'><i class="fa fa-times-circle"></i></a>
<a href {{action "close"}} title='{{i18n 'share.close'}}'>{{fa-icon "times-circle"}}</a>
</div>
{{/if}}

View File

@ -1,5 +0,0 @@
{{#if s.openInPopup}}
<a href {{action "sharePopup" s.target s.href}} {{bind-attr title="title"}}><i {{bind-attr class=":fa s.iconClass"}}></i></a>
{{else}}
<a {{bind-attr href="s.href"}} {{bind-attr title="s.title"}} target="_blank"><i {{bind-attr class=":fa s.iconClass"}}></i></a>
{{/if}}

View File

@ -1,5 +0,0 @@
export default Ember.View.extend({
templateName: 'share_link',
tagName: 'div',
classNameBindings: [':social-link']
});

View File

@ -1,11 +1,3 @@
/**
This view is used for rendering the "share" interface for a post
@class ShareView
@extends Discourse.View
@namespace Discourse
@module Discourse
**/
export default Discourse.View.extend({
templateName: 'share',
elementId: 'share-link',

View File

@ -59,6 +59,7 @@
//= require ./discourse/lib/export-result
//= require ./discourse/dialects/dialect
//= require ./discourse/lib/emoji/emoji
//= require ./discourse/lib/sharing
//= require_tree ./discourse/dialects
//= require_tree ./discourse/controllers