FIX: rare user card exception

- trigger the shown logic in user card view
- some tweaks to user card show logic
This commit is contained in:
Erick Guan 2015-05-25 22:34:57 +08:00
parent ff55bcb4d0
commit 54adf72582
3 changed files with 46 additions and 44 deletions

View File

@ -1,10 +1,12 @@
export default Ember.Component.extend({ export default Ember.Component.extend({
_parse: function() { _parse: function() {
this.$().find('hr').remove(); Ember.run.next(null, () => {
this.$().ellipsis(); this.$().find('hr').remove();
this.$().ellipsis();
});
}.on('didInsertElement'), }.on('didInsertElement'),
render: function(buffer) { render(buffer) {
buffer.push(this.get('text')); buffer.push(this.get('text'));
} }
}); });

View File

@ -35,35 +35,32 @@ export default Ember.Controller.extend({
show(username, postId, target) { show(username, postId, target) {
// XSS protection (should be encapsulated) // XSS protection (should be encapsulated)
username = username.toString().replace(/[^A-Za-z0-9_]/g, ""); username = username.toString().replace(/[^A-Za-z0-9_]/g, "");
const url = "/users/" + username;
// Don't show on mobile // Don't show on mobile
if (Discourse.Mobile.mobileView) { if (Discourse.Mobile.mobileView) {
const url = "/users/" + username;
Discourse.URL.routeTo(url); Discourse.URL.routeTo(url);
return; return;
} }
const currentUsername = this.get('username'), const currentUsername = this.get('username'),
wasVisible = this.get('visible'), wasVisible = this.get('visible'),
post = this.get('viewingTopic') && postId ? this.get('postStream').findLoadedPost(postId) : null; previousTarget = this.get('cardTarget'),
post = this.get('viewingTopic') && postId ? this.get('postStream').findLoadedPost(postId) : null;
this.setProperties({ avatar: null, post: post, username: username });
if (wasVisible) {
if (target === this.get('cardTarget')) {
this.close();
return; // Same target, close it without loading the new user card
} else {
this.close();
}
}
if (username === currentUsername && this.get('userLoading') === username) { if (username === currentUsername && this.get('userLoading') === username) {
// debounce // debounce
return; return;
} }
this.setProperties({ user: null, username, userLoading: username, cardTarget: target, topicPostCount: null }); if (wasVisible) {
this.close();
if (target === previousTarget) {
return; // Same target, close it without loading the new user card
}
}
this.setProperties({ username, userLoading: username, cardTarget: target, post });
const args = { stats: false }; const args = { stats: false };
args.include_post_count_for = this.get('controllers.topic.model.id'); args.include_post_count_for = this.get('controllers.topic.model.id');
@ -72,9 +69,7 @@ export default Ember.Controller.extend({
if (user.topic_post_count) { if (user.topic_post_count) {
this.set('topicPostCount', user.topic_post_count[args.include_post_count_for]); this.set('topicPostCount', user.topic_post_count[args.include_post_count_for]);
} }
user = Discourse.User.create(user);
this.setProperties({ user, avatar: user, visible: true }); this.setProperties({ user, avatar: user, visible: true });
this.appEvents.trigger('usercard:shown');
}).catch((error) => { }).catch((error) => {
this.close(); this.close();
throw error; throw error;
@ -84,7 +79,16 @@ export default Ember.Controller.extend({
}, },
close() { close() {
this.setProperties({ visible: false, username: null, cardTarget: null }); this.setProperties({
visible: false,
user: null,
username: null,
avatar: null,
userLoading: null,
cardTarget: null,
post: null,
topicPostCount: null
});
}, },
actions: { actions: {

View File

@ -3,8 +3,8 @@ import CleansUp from 'discourse/mixins/cleans-up';
import afterTransition from 'discourse/lib/after-transition'; import afterTransition from 'discourse/lib/after-transition';
const clickOutsideEventName = "mousedown.outside-user-card", const clickOutsideEventName = "mousedown.outside-user-card",
clickDataExpand = "click.discourse-user-card", clickDataExpand = "click.discourse-user-card",
clickMention = "click.discourse-user-mention"; clickMention = "click.discourse-user-mention";
export default Discourse.View.extend(CleansUp, { export default Discourse.View.extend(CleansUp, {
elementId: 'user-card', elementId: 'user-card',
@ -30,30 +30,26 @@ export default Discourse.View.extend(CleansUp, {
afterTransition(this.$(), this._hide.bind(this)); afterTransition(this.$(), this._hide.bind(this));
$('html').off(clickOutsideEventName) $('html').off(clickOutsideEventName)
.on(clickOutsideEventName, (e) => { .on(clickOutsideEventName, (e) => {
if (this.get('controller.visible')) { if (this.get('controller.visible')) {
const $target = $(e.target); const $target = $(e.target);
if ($target.closest('[data-user-card]').data('userCard') || if ($target.closest('[data-user-card]').data('userCard') ||
$target.closest('a.mention').length > 0 || $target.closest('a.mention').length > 0 ||
$target.closest('#user-card').length > 0) { $target.closest('#user-card').length > 0) {
return; return;
}
this.get('controller').close();
} }
this.get('controller').close(); return true;
} });
return true;
});
const expand = (username, $target) => { const expand = (username, $target) => {
const postId = $target.parents('article').data('post-id'), const postId = $target.parents('article').data('post-id'),
user = this.get('controller').show(username, postId, $target[0]); user = this.get('controller').show(username, postId, $target[0]);
if (user !== undefined) { if (user !== undefined) {
user.then(() => { user.then( () => this._willShow($target) ).catch( () => this._hide() );
this._willShow($target);
}).catch(() => {
this._hide();
});
} else { } else {
this._hide(); this._hide();
} }
@ -64,7 +60,7 @@ export default Discourse.View.extend(CleansUp, {
if (e.ctrlKey || e.metaKey) { return; } if (e.ctrlKey || e.metaKey) { return; }
const $target = $(e.currentTarget), const $target = $(e.currentTarget),
username = $target.data('user-card'); username = $target.data('user-card');
return expand(username, $target); return expand(username, $target);
}); });
@ -72,10 +68,9 @@ export default Discourse.View.extend(CleansUp, {
if (e.ctrlKey || e.metaKey) { return; } if (e.ctrlKey || e.metaKey) { return; }
const $target = $(e.target), const $target = $(e.target),
username = $target.text().replace(/^@/, ''); username = $target.text().replace(/^@/, '');
return expand(username, $target); return expand(username, $target);
}); });
this.appEvents.on('usercard:shown', this, '_shown'); this.appEvents.on('usercard:shown', this, '_shown');
}.on('didInsertElement'), }.on('didInsertElement'),
@ -91,7 +86,7 @@ export default Discourse.View.extend(CleansUp, {
_willShow(target) { _willShow(target) {
if (!target) { return; } if (!target) { return; }
const width = this.$().width(); const width = this.$().width();
Em.run.schedule('afterRender', () => { Ember.run.schedule('afterRender', () => {
if (target) { if (target) {
let position = target.offset(); let position = target.offset();
if (position) { if (position) {
@ -106,6 +101,7 @@ export default Discourse.View.extend(CleansUp, {
position.top -= $('#main-outlet').offset().top; position.top -= $('#main-outlet').offset().top;
this.$().css(position); this.$().css(position);
} }
this.appEvents.trigger('usercard:shown');
} }
}); });
}, },
@ -132,7 +128,7 @@ export default Discourse.View.extend(CleansUp, {
$('html').off(clickOutsideEventName); $('html').off(clickOutsideEventName);
$('#main').off(clickDataExpand) $('#main').off(clickDataExpand)
.off(clickMention); .off(clickMention);
this.appEvents.off('usercard:shown', this, '_shown'); this.appEvents.off('usercard:shown', this, '_shown');
}.on('willDestroyElement') }.on('willDestroyElement')