REFACTOR: Cleaner `quoteButton` object, and some bug fixes
This commit is contained in:
parent
477b237e45
commit
da76dd3d6b
|
@ -1,4 +1,3 @@
|
||||||
import computed from 'ember-addons/ember-computed-decorators';
|
|
||||||
import { selectedText } from 'discourse/lib/utilities';
|
import { selectedText } from 'discourse/lib/utilities';
|
||||||
|
|
||||||
// we don't want to deselect when we click on buttons that use it
|
// we don't want to deselect when we click on buttons that use it
|
||||||
|
@ -10,17 +9,22 @@ function willQuote(e) {
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
classNames: ['quote-button'],
|
classNames: ['quote-button'],
|
||||||
classNameBindings: ['visible'],
|
classNameBindings: ['visible'],
|
||||||
|
visible: false,
|
||||||
@computed('quoteState.buffer')
|
|
||||||
visible: buffer => buffer && buffer.length > 0,
|
|
||||||
|
|
||||||
_isMouseDown: false,
|
_isMouseDown: false,
|
||||||
_reselected: false,
|
_reselected: false,
|
||||||
|
|
||||||
|
_hideButton() {
|
||||||
|
this.get('quoteState').clear();
|
||||||
|
this.set('visible', false);
|
||||||
|
},
|
||||||
|
|
||||||
_selectionChanged() {
|
_selectionChanged() {
|
||||||
|
const quoteState = this.get('quoteState');
|
||||||
|
|
||||||
const selection = window.getSelection();
|
const selection = window.getSelection();
|
||||||
if (selection.isCollapsed) {
|
if (selection.isCollapsed) {
|
||||||
if (this.get("visible")) this.sendAction("deselectText");
|
if (this.get("visible")) { this._hideButton(); }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,12 +38,13 @@ export default Ember.Component.extend({
|
||||||
postId = postId || $ancestor.closest('.boxed, .reply').data('post-id');
|
postId = postId || $ancestor.closest('.boxed, .reply').data('post-id');
|
||||||
|
|
||||||
if ($ancestor.closest(".contents").length === 0 || !postId) {
|
if ($ancestor.closest(".contents").length === 0 || !postId) {
|
||||||
if (this.get("visible")) this.sendAction("deselectText");
|
if (this.get("visible")) { this._hideButton(); }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.get("quoteState").setProperties({ postId, buffer: selectedText() });
|
quoteState.selected(postId, selectedText());
|
||||||
|
this.set('visible', quoteState.buffer.length > 0);
|
||||||
|
|
||||||
// on Desktop, shows the button at the beginning of the selection
|
// on Desktop, shows the button at the beginning of the selection
|
||||||
// on Mobile, shows the button at the end of the selection
|
// on Mobile, shows the button at the end of the selection
|
||||||
|
@ -97,11 +102,11 @@ export default Ember.Component.extend({
|
||||||
const wait = (isWinphone || isAndroid) ? 250 : 25;
|
const wait = (isWinphone || isAndroid) ? 250 : 25;
|
||||||
const onSelectionChanged = _.debounce(() => this._selectionChanged(), wait);
|
const onSelectionChanged = _.debounce(() => this._selectionChanged(), wait);
|
||||||
|
|
||||||
$(document).on("mousedown.quote-button", (e) => {
|
$(document).on("mousedown.quote-button", e => {
|
||||||
this._isMouseDown = true;
|
this._isMouseDown = true;
|
||||||
this._reselected = false;
|
this._reselected = false;
|
||||||
if (!willQuote(e)) {
|
if (!willQuote(e)) {
|
||||||
this.sendAction("deselectText");
|
this._hideButton();
|
||||||
}
|
}
|
||||||
}).on("mouseup.quote-button", () => {
|
}).on("mouseup.quote-button", () => {
|
||||||
this._isMouseDown = false;
|
this._isMouseDown = false;
|
||||||
|
@ -120,7 +125,8 @@ export default Ember.Component.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
click() {
|
click() {
|
||||||
this.sendAction("selectText");
|
const { postId, buffer } = this.get('quoteState');
|
||||||
|
this.attrs.selectText(postId, buffer).then(() => this._hideButton());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { categoryBadgeHTML } from 'discourse/helpers/category-link';
|
||||||
import Post from 'discourse/models/post';
|
import Post from 'discourse/models/post';
|
||||||
import debounce from 'discourse/lib/debounce';
|
import debounce from 'discourse/lib/debounce';
|
||||||
import isElementInViewport from "discourse/lib/is-element-in-viewport";
|
import isElementInViewport from "discourse/lib/is-element-in-viewport";
|
||||||
|
import QuoteState from 'discourse/lib/quote-state';
|
||||||
|
|
||||||
export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
composer: Ember.inject.controller(),
|
composer: Ember.inject.controller(),
|
||||||
|
@ -119,7 +120,7 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
this._super();
|
this._super();
|
||||||
this.set('selectedPosts', []);
|
this.set('selectedPosts', []);
|
||||||
this.set('selectedReplies', []);
|
this.set('selectedReplies', []);
|
||||||
this.set('quoteState', Ember.Object.create({ buffer: null, postId: null }));
|
this.set('quoteState', new QuoteState());
|
||||||
},
|
},
|
||||||
|
|
||||||
showCategoryChooser: Ember.computed.not("model.isPrivateMessage"),
|
showCategoryChooser: Ember.computed.not("model.isPrivateMessage"),
|
||||||
|
@ -167,16 +168,8 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
this.send('showFeatureTopic');
|
this.send('showFeatureTopic');
|
||||||
},
|
},
|
||||||
|
|
||||||
deselectText() {
|
selectText(postId, buffer) {
|
||||||
this.get('quoteState').setProperties({ buffer: null, postId: null });
|
return this.get('model.postStream').loadPost(postId).then(post => {
|
||||||
},
|
|
||||||
|
|
||||||
selectText() {
|
|
||||||
const { postId, buffer } = this.get('quoteState');
|
|
||||||
|
|
||||||
this.send('deselectText');
|
|
||||||
|
|
||||||
this.get('model.postStream').loadPost(postId).then(post => {
|
|
||||||
// If we can't create a post, delegate to reply as new topic
|
// If we can't create a post, delegate to reply as new topic
|
||||||
if (!this.get('model.details.can_create_post')) {
|
if (!this.get('model.details.can_create_post')) {
|
||||||
this.send('replyAsNewTopic', post);
|
this.send('replyAsNewTopic', post);
|
||||||
|
@ -196,15 +189,19 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
|
|
||||||
// If the composer is associated with a different post, we don't change it.
|
// If the composer is associated with a different post, we don't change it.
|
||||||
const composer = this.get('composer');
|
const composer = this.get('composer');
|
||||||
const composerPost = composer.get('content.post');
|
const composerPost = composer.get('model.post');
|
||||||
if (composerPost && (composerPost.get('id') !== this.get('post.id'))) {
|
if (composerPost && (composerPost.get('id') !== this.get('post.id'))) {
|
||||||
composerOpts.post = composerPost;
|
composerOpts.post = composerPost;
|
||||||
}
|
}
|
||||||
|
|
||||||
const quotedText = Quote.build(post, buffer);
|
const quotedText = Quote.build(post, buffer);
|
||||||
composerOpts.quote = quotedText;
|
composerOpts.quote = quotedText;
|
||||||
if (composer.get('content.viewOpen') || composer.get('content.viewDraft')) {
|
if (composer.get('model.viewOpen')) {
|
||||||
this.appEvents.trigger('composer:insert-text', quotedText);
|
this.appEvents.trigger('composer:insert-text', quotedText);
|
||||||
|
} else if (composer.get('model.viewDraft')) {
|
||||||
|
const model = composer.get('model');
|
||||||
|
model.set('reply', model.get('reply') + quotedText);
|
||||||
|
composer.send('openIfDraft');
|
||||||
} else {
|
} else {
|
||||||
composer.open(composerOpts);
|
composer.open(composerOpts);
|
||||||
}
|
}
|
||||||
|
@ -314,9 +311,10 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
|
|
||||||
const quoteState = this.get('quoteState');
|
const quoteState = this.get('quoteState');
|
||||||
const postStream = this.get('model.postStream');
|
const postStream = this.get('model.postStream');
|
||||||
const quotedPost = postStream.findLoadedPost(quoteState.get('postId'));
|
const quotedPost = postStream.findLoadedPost(quoteState.postId);
|
||||||
const quotedText = Quote.build(quotedPost, quoteState.get('buffer'));
|
const quotedText = Quote.build(quotedPost, quoteState.buffer);
|
||||||
this.send('deselectText');
|
|
||||||
|
quoteState.clear();
|
||||||
|
|
||||||
if (composerController.get('content.topic.id') === topic.get('id') &&
|
if (composerController.get('content.topic.id') === topic.get('id') &&
|
||||||
composerController.get('content.action') === Composer.REPLY) {
|
composerController.get('content.action') === Composer.REPLY) {
|
||||||
|
@ -652,10 +650,9 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
replyAsNewTopic(post) {
|
replyAsNewTopic(post) {
|
||||||
const composerController = this.get('composer');
|
const composerController = this.get('composer');
|
||||||
|
|
||||||
const quoteState = this.get('quoteState');
|
const { quoteState } = this;
|
||||||
post = post || quoteState.get('post');
|
const quotedText = Quote.build(post, quoteState.buffer);
|
||||||
const quotedText = Quote.build(post, quoteState.get('buffer'));
|
quoteState.clear();
|
||||||
this.send('deselectText');
|
|
||||||
|
|
||||||
composerController.open({
|
composerController.open({
|
||||||
action: Composer.CREATE_TOPIC,
|
action: Composer.CREATE_TOPIC,
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
export default class QuoteState {
|
||||||
|
constructor() {
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
selected(postId, buffer) {
|
||||||
|
this.postId = postId;
|
||||||
|
this.buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.buffer = '';
|
||||||
|
this.postId = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -117,7 +117,6 @@ const TopicRoute = Discourse.Route.extend({
|
||||||
|
|
||||||
willTransition() {
|
willTransition() {
|
||||||
this._super();
|
this._super();
|
||||||
this.controllerFor("topic").send('deselectText');
|
|
||||||
Em.run.cancel(scheduledReplace);
|
Em.run.cancel(scheduledReplace);
|
||||||
isTransitioning = true;
|
isTransitioning = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -207,6 +206,7 @@ const TopicRoute = Discourse.Route.extend({
|
||||||
|
|
||||||
// close the multi select when switching topics
|
// close the multi select when switching topics
|
||||||
controller.set('multiSelect', false);
|
controller.set('multiSelect', false);
|
||||||
|
controller.get('quoteState').clear();
|
||||||
|
|
||||||
this.controllerFor('composer').set('topic', model);
|
this.controllerFor('composer').set('topic', model);
|
||||||
this.topicTrackingState.trackIncoming('all');
|
this.topicTrackingState.trackIncoming('all');
|
||||||
|
|
|
@ -273,8 +273,6 @@
|
||||||
{{share-popup topic=model replyAsNewTopic="replyAsNewTopic"}}
|
{{share-popup topic=model replyAsNewTopic="replyAsNewTopic"}}
|
||||||
|
|
||||||
{{#if currentUser.enable_quoting}}
|
{{#if currentUser.enable_quoting}}
|
||||||
{{quote-button quoteState=quoteState
|
{{quote-button quoteState=quoteState selectText=(action "selectText")}}
|
||||||
selectText="selectText"
|
|
||||||
deselectText="deselectText"}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/discourse-topic}}
|
{{/discourse-topic}}
|
||||||
|
|
Loading…
Reference in New Issue