mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-30 10:58:31 -05:00
Refactor topic-progress
into a component
This commit is contained in:
parent
4a7567b485
commit
751e354ca6
11 changed files with 229 additions and 243 deletions
|
@ -0,0 +1,205 @@
|
||||||
|
import DiscourseURL from 'discourse/lib/url';
|
||||||
|
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
elementId: 'topic-progress-wrapper',
|
||||||
|
classNameBindings: ['docked'],
|
||||||
|
expanded: false,
|
||||||
|
toPostIndex: null,
|
||||||
|
docked: false,
|
||||||
|
|
||||||
|
postStream: Ember.computed.alias('topic.postStream'),
|
||||||
|
|
||||||
|
@computed('postStream.loaded', 'progressPosition', 'postStream.filteredPostsCount', 'postStream.highest_post_number')
|
||||||
|
streamPercentage(loaded, progressPosition, filteredPostsCount, highestPostNumber) {
|
||||||
|
if (!loaded) { return 0; }
|
||||||
|
if (highestPostNumber === 0) { return 0; }
|
||||||
|
const perc = progressPosition / filteredPostsCount;
|
||||||
|
return (perc > 1.0) ? 1.0 : perc;
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed('progressPosition')
|
||||||
|
jumpTopDisabled(progressPosition) {
|
||||||
|
return progressPosition <= 3;
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed('postStream.filteredPostsCount', 'topic.highest_post_number', 'progressPosition')
|
||||||
|
jumpBottomDisabled(filteredPostsCount, highestPostNumber, progressPosition) {
|
||||||
|
return progressPosition >= filteredPostsCount || progressPosition >= highestPostNumber;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@computed('postStream.loaded', 'topic.currentPost', 'postStream.filteredPostsCount')
|
||||||
|
hideProgress(loaded, currentPost, filteredPostsCount) {
|
||||||
|
return (!loaded) || (!currentPost) || (filteredPostsCount < 2);
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed('postStream.filteredPostsCount')
|
||||||
|
hugeNumberOfPosts(filteredPostsCount) {
|
||||||
|
return filteredPostsCount >= this.siteSettings.short_progress_text_threshold;
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed('hugeNumberOfPosts', 'topic.highest_post_number')
|
||||||
|
jumpToBottomTitle(hugeNumberOfPosts, highestPostNumber) {
|
||||||
|
if (hugeNumberOfPosts) {
|
||||||
|
return I18n.t('topic.progress.jump_bottom_with_number', { post_number: highestPostNumber });
|
||||||
|
} else {
|
||||||
|
return I18n.t('topic.progress.jump_bottom');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@observes('streamPercentage', 'postStream.stream.[]')
|
||||||
|
_updateBar() {
|
||||||
|
Ember.run.scheduleOnce('afterRender', this, this._updateProgressBar);
|
||||||
|
},
|
||||||
|
|
||||||
|
didInsertElement() {
|
||||||
|
this._super();
|
||||||
|
this.appEvents.on("composer:opened", this, this._dock)
|
||||||
|
.on("composer:resized", this, this._dock)
|
||||||
|
.on("composer:closed", this, this._dock)
|
||||||
|
.on("topic:scrolled", this, this._dock);
|
||||||
|
|
||||||
|
// Reflows are expensive. Cache the jQuery selector
|
||||||
|
// and the width when inserted into the DOM
|
||||||
|
this._$topicProgress = this.$('#topic-progress');
|
||||||
|
|
||||||
|
Ember.run.scheduleOnce('afterRender', this, this._updateProgressBar);
|
||||||
|
},
|
||||||
|
|
||||||
|
willDestroyElement() {
|
||||||
|
this._super();
|
||||||
|
this.appEvents.off("composer:opened", this, this._dock)
|
||||||
|
.off("composer:resized", this, this._dock)
|
||||||
|
.off("composer:closed", this, this._dock)
|
||||||
|
.off('topic:scrolled', this, this._dock);
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateProgressBar() {
|
||||||
|
// speeds up stuff, bypass jquery slowness and extra checks
|
||||||
|
if (!this._totalWidth) {
|
||||||
|
this._totalWidth = this._$topicProgress[0].offsetWidth;
|
||||||
|
}
|
||||||
|
const totalWidth = this._totalWidth;
|
||||||
|
const progressWidth = this.get('streamPercentage') * totalWidth;
|
||||||
|
|
||||||
|
this._$topicProgress.find('.bg')
|
||||||
|
.css("border-right-width", (progressWidth === totalWidth) ? "0px" : "1px")
|
||||||
|
.width(progressWidth);
|
||||||
|
},
|
||||||
|
|
||||||
|
_dock() {
|
||||||
|
const maximumOffset = $('#topic-footer-buttons').offset(),
|
||||||
|
composerHeight = $('#reply-control').height() || 0,
|
||||||
|
$topicProgressWrapper = this.$(),
|
||||||
|
style = $topicProgressWrapper.attr('style') || '',
|
||||||
|
offset = window.pageYOffset || $('html').scrollTop();
|
||||||
|
|
||||||
|
let isDocked = false;
|
||||||
|
if (maximumOffset) {
|
||||||
|
const threshold = maximumOffset.top,
|
||||||
|
windowHeight = $(window).height(),
|
||||||
|
topicProgressHeight = $('#topic-progress').height();
|
||||||
|
|
||||||
|
isDocked = offset >= threshold - windowHeight + topicProgressHeight + composerHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (composerHeight > 0) {
|
||||||
|
if (isDocked) {
|
||||||
|
if (style.indexOf('bottom') >= 0) {
|
||||||
|
$topicProgressWrapper.css('bottom', '');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const height = composerHeight + "px";
|
||||||
|
if ($topicProgressWrapper.css('bottom') !== height) {
|
||||||
|
$topicProgressWrapper.css('bottom', height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (style.indexOf('bottom') >= 0) {
|
||||||
|
$topicProgressWrapper.css('bottom', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.set('docked', isDocked);
|
||||||
|
},
|
||||||
|
|
||||||
|
click(e) {
|
||||||
|
if ($(e.target).parents('#topic-progress').length) {
|
||||||
|
this.send('toggleExpansion');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
keyDown(e) {
|
||||||
|
if (this.get('expanded')) {
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
this.$('input').blur();
|
||||||
|
this.send('jumpPost');
|
||||||
|
} else if (e.keyCode === 27) {
|
||||||
|
this.send('toggleExpansion');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jumpTo(url) {
|
||||||
|
this.set('expanded', false);
|
||||||
|
DiscourseURL.routeTo(url);
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
toggleExpansion(opts) {
|
||||||
|
this.toggleProperty('expanded');
|
||||||
|
if (this.get('expanded')) {
|
||||||
|
this.set('toPostIndex', this.get('progressPosition'));
|
||||||
|
if(opts && opts.highlight){
|
||||||
|
// TODO: somehow move to view?
|
||||||
|
Em.run.next(function(){
|
||||||
|
$('.jump-form input').select().focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!this.site.mobileView && !this.capabilities.isIOS) {
|
||||||
|
Ember.run.schedule('afterRender', () => this.$('input').focus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jumpPost() {
|
||||||
|
let postIndex = parseInt(this.get('toPostIndex'), 10);
|
||||||
|
|
||||||
|
// Validate the post index first
|
||||||
|
if (isNaN(postIndex) || postIndex < 1) {
|
||||||
|
postIndex = 1;
|
||||||
|
}
|
||||||
|
if (postIndex > this.get('postStream.filteredPostsCount')) {
|
||||||
|
postIndex = this.get('postStream.filteredPostsCount');
|
||||||
|
}
|
||||||
|
this.set('toPostIndex', postIndex);
|
||||||
|
const stream = this.get('postStream');
|
||||||
|
const postId = stream.findPostIdForPostNumber(postIndex);
|
||||||
|
|
||||||
|
if (!postId) {
|
||||||
|
Em.Logger.warn("jump-post code broken - requested an index outside the stream array");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const post = stream.findLoadedPost(postId);
|
||||||
|
if (post) {
|
||||||
|
this.jumpTo(this.get('topic').urlForPostNumber(post.get('post_number')));
|
||||||
|
} else {
|
||||||
|
// need to load it
|
||||||
|
stream.findPostsByIds([postId]).then(arr => {
|
||||||
|
this.jumpTo(this.get('topic').urlForPostNumber(arr[0].get('post_number')));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jumpTop() {
|
||||||
|
this.set('expanded', false);
|
||||||
|
this.sendAction('jumpTop');
|
||||||
|
},
|
||||||
|
|
||||||
|
jumpBottom() {
|
||||||
|
this.set('expanded', false);
|
||||||
|
this.sendAction('jumpBottom');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,111 +0,0 @@
|
||||||
import DiscourseURL from 'discourse/lib/url';
|
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
|
||||||
needs: ['topic'],
|
|
||||||
progressPosition: null,
|
|
||||||
expanded: false,
|
|
||||||
toPostIndex: null,
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
toggleExpansion(opts) {
|
|
||||||
this.toggleProperty('expanded');
|
|
||||||
if (this.get('expanded')) {
|
|
||||||
this.set('toPostIndex', this.get('progressPosition'));
|
|
||||||
if(opts && opts.highlight){
|
|
||||||
// TODO: somehow move to view?
|
|
||||||
Em.run.next(function(){
|
|
||||||
$('.jump-form input').select().focus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
jumpPost() {
|
|
||||||
var postIndex = parseInt(this.get('toPostIndex'), 10);
|
|
||||||
|
|
||||||
// Validate the post index first
|
|
||||||
if (isNaN(postIndex) || postIndex < 1) {
|
|
||||||
postIndex = 1;
|
|
||||||
}
|
|
||||||
if (postIndex > this.get('model.postStream.filteredPostsCount')) {
|
|
||||||
postIndex = this.get('model.postStream.filteredPostsCount');
|
|
||||||
}
|
|
||||||
this.set('toPostIndex', postIndex);
|
|
||||||
var stream = this.get('model.postStream'),
|
|
||||||
postId = stream.findPostIdForPostNumber(postIndex);
|
|
||||||
|
|
||||||
if (!postId) {
|
|
||||||
Em.Logger.warn("jump-post code broken - requested an index outside the stream array");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var post = stream.findLoadedPost(postId);
|
|
||||||
if (post) {
|
|
||||||
this.jumpTo(this.get('model').urlForPostNumber(post.get('post_number')));
|
|
||||||
} else {
|
|
||||||
var self = this;
|
|
||||||
// need to load it
|
|
||||||
stream.findPostsByIds([postId]).then(function(arr) {
|
|
||||||
post = arr[0];
|
|
||||||
self.jumpTo(self.get('model').urlForPostNumber(post.get('post_number')));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
jumpTop() {
|
|
||||||
this.jumpTo(this.get('model.firstPostUrl'));
|
|
||||||
},
|
|
||||||
|
|
||||||
jumpBottom() {
|
|
||||||
this.jumpTo(this.get('model.lastPostUrl'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Route and close the expansion
|
|
||||||
jumpTo(url) {
|
|
||||||
this.set('expanded', false);
|
|
||||||
DiscourseURL.routeTo(url);
|
|
||||||
},
|
|
||||||
|
|
||||||
streamPercentage: function() {
|
|
||||||
if (!this.get('model.postStream.loaded')) { return 0; }
|
|
||||||
if (this.get('model.postStream.highest_post_number') === 0) { return 0; }
|
|
||||||
var perc = this.get('progressPosition') / this.get('model.postStream.filteredPostsCount');
|
|
||||||
return (perc > 1.0) ? 1.0 : perc;
|
|
||||||
}.property('model.postStream.loaded', 'progressPosition', 'model.postStream.filteredPostsCount'),
|
|
||||||
|
|
||||||
jumpTopDisabled: function() {
|
|
||||||
return this.get('progressPosition') <= 3;
|
|
||||||
}.property('progressPosition'),
|
|
||||||
|
|
||||||
filteredPostCountChanged: function(){
|
|
||||||
if(this.get('model.postStream.filteredPostsCount') < this.get('progressPosition')){
|
|
||||||
this.set('progressPosition', this.get('model.postStream.filteredPostsCount'));
|
|
||||||
}
|
|
||||||
}.observes('model.postStream.filteredPostsCount'),
|
|
||||||
|
|
||||||
jumpBottomDisabled: function() {
|
|
||||||
return this.get('progressPosition') >= this.get('model.postStream.filteredPostsCount') ||
|
|
||||||
this.get('progressPosition') >= this.get('model.highest_post_number');
|
|
||||||
}.property('model.postStream.filteredPostsCount', 'model.highest_post_number', 'progressPosition'),
|
|
||||||
|
|
||||||
hideProgress: function() {
|
|
||||||
if (!this.get('model.postStream.loaded')) return true;
|
|
||||||
if (!this.get('model.currentPost')) return true;
|
|
||||||
if (this.get('model.postStream.filteredPostsCount') < 2) return true;
|
|
||||||
return false;
|
|
||||||
}.property('model.postStream.loaded', 'model.currentPost', 'model.postStream.filteredPostsCount'),
|
|
||||||
|
|
||||||
hugeNumberOfPosts: function() {
|
|
||||||
return (this.get('model.postStream.filteredPostsCount') >= Discourse.SiteSettings.short_progress_text_threshold);
|
|
||||||
}.property('model.highest_post_number'),
|
|
||||||
|
|
||||||
jumpToBottomTitle: function() {
|
|
||||||
if (this.get('hugeNumberOfPosts')) {
|
|
||||||
return I18n.t('topic.progress.jump_bottom_with_number', {post_number: this.get('model.highest_post_number')});
|
|
||||||
} else {
|
|
||||||
return I18n.t('topic.progress.jump_bottom');
|
|
||||||
}
|
|
||||||
}.property('hugeNumberOfPosts', 'model.highest_post_number')
|
|
||||||
|
|
||||||
});
|
|
|
@ -10,7 +10,7 @@ import DiscourseURL from 'discourse/lib/url';
|
||||||
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
|
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
|
||||||
|
|
||||||
export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
needs: ['modal', 'composer', 'quote-button', 'topic-progress', 'application'],
|
needs: ['modal', 'composer', 'quote-button', 'application'],
|
||||||
multiSelect: false,
|
multiSelect: false,
|
||||||
allPostsSelected: false,
|
allPostsSelected: false,
|
||||||
editingTopic: false,
|
editingTopic: false,
|
||||||
|
@ -21,10 +21,16 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
enteredAt: null,
|
enteredAt: null,
|
||||||
retrying: false,
|
retrying: false,
|
||||||
adminMenuVisible: false,
|
adminMenuVisible: false,
|
||||||
|
screenProgressPosition: null,
|
||||||
|
|
||||||
showRecover: Em.computed.and('model.deleted', 'model.details.can_recover'),
|
showRecover: Em.computed.and('model.deleted', 'model.details.can_recover'),
|
||||||
isFeatured: Em.computed.or("model.pinned_at", "model.isBanner"),
|
isFeatured: Em.computed.or("model.pinned_at", "model.isBanner"),
|
||||||
|
|
||||||
|
@computed('screenProgressPosition', 'model.postStream.filteredPostsCount')
|
||||||
|
progressPosition(pp, filteredPostsCount) {
|
||||||
|
return (filteredPostsCount < pp) ? filteredPostsCount : pp;
|
||||||
|
},
|
||||||
|
|
||||||
_titleChanged: function() {
|
_titleChanged: function() {
|
||||||
const title = this.get('model.title');
|
const title = this.get('model.title');
|
||||||
if (!Ember.isEmpty(title)) {
|
if (!Ember.isEmpty(title)) {
|
||||||
|
@ -203,7 +209,7 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
const postStream = this.get('model.postStream');
|
const postStream = this.get('model.postStream');
|
||||||
const lastLoadedPost = postStream.get('posts.lastObject');
|
const lastLoadedPost = postStream.get('posts.lastObject');
|
||||||
|
|
||||||
this.set('controllers.topic-progress.progressPosition', postStream.progressIndexOfPost(post));
|
this.set('screenProgressPosition', postStream.progressIndexOfPost(post));
|
||||||
|
|
||||||
if (lastLoadedPost && lastLoadedPost === post && postStream.get('canAppendMore')) {
|
if (lastLoadedPost && lastLoadedPost === post && postStream.get('canAppendMore')) {
|
||||||
postStream.appendMore().then(() => refresh());
|
postStream.appendMore().then(() => refresh());
|
||||||
|
@ -379,7 +385,11 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||||
},
|
},
|
||||||
|
|
||||||
jumpTop() {
|
jumpTop() {
|
||||||
this.get('controllers.topic-progress').send('jumpTop');
|
DiscourseURL.routeTo(this.get('model.firstPostUrl'));
|
||||||
|
},
|
||||||
|
|
||||||
|
jumpBottom() {
|
||||||
|
DiscourseURL.routeTo(this.get('model.lastPostUrl'));
|
||||||
},
|
},
|
||||||
|
|
||||||
selectAll() {
|
selectAll() {
|
||||||
|
|
|
@ -116,7 +116,7 @@ export default {
|
||||||
|
|
||||||
_jumpTo(direction) {
|
_jumpTo(direction) {
|
||||||
if ($('.container.posts').length) {
|
if ($('.container.posts').length) {
|
||||||
this.container.lookup('controller:topic-progress').send(direction);
|
this.container.lookup('controller:topic').send(direction);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -232,11 +232,6 @@ const DiscourseURL = Ember.Object.extend({
|
||||||
enteredAt: new Date().getTime().toString()
|
enteredAt: new Date().getTime().toString()
|
||||||
});
|
});
|
||||||
|
|
||||||
const closestPost = postStream.closestPostForPostNumber(closest);
|
|
||||||
const progress = postStream.progressIndexOfPost(closestPost);
|
|
||||||
const progressController = container.lookup('controller:topic-progress');
|
|
||||||
|
|
||||||
progressController.set('progressPosition', progress);
|
|
||||||
this.appEvents.trigger('post:highlight', closest);
|
this.appEvents.trigger('post:highlight', closest);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
DiscourseURL.jumpToPost(closest, {skipIfOnScreen: true});
|
DiscourseURL.jumpToPost(closest, {skipIfOnScreen: true});
|
||||||
|
|
|
@ -15,7 +15,6 @@ export default Discourse.Route.extend({
|
||||||
topic = this.modelFor('topic'),
|
topic = this.modelFor('topic'),
|
||||||
postStream = topic.get('postStream'),
|
postStream = topic.get('postStream'),
|
||||||
topicController = this.controllerFor('topic'),
|
topicController = this.controllerFor('topic'),
|
||||||
topicProgressController = this.controllerFor('topic-progress'),
|
|
||||||
composerController = this.controllerFor('composer');
|
composerController = this.controllerFor('composer');
|
||||||
|
|
||||||
// I sincerely hope no topic gets this many posts
|
// I sincerely hope no topic gets this many posts
|
||||||
|
@ -28,20 +27,14 @@ export default Discourse.Route.extend({
|
||||||
// we need better handling and logging for this condition.
|
// we need better handling and logging for this condition.
|
||||||
|
|
||||||
// The post we requested might not exist. Let's find the closest post
|
// The post we requested might not exist. Let's find the closest post
|
||||||
const closestPost = postStream.closestPostForPostNumber(params.nearPost || 1),
|
const closestPost = postStream.closestPostForPostNumber(params.nearPost || 1);
|
||||||
closest = closestPost.get('post_number'),
|
const closest = closestPost.get('post_number');
|
||||||
progress = postStream.progressIndexOfPost(closestPost);
|
|
||||||
|
|
||||||
topicController.setProperties({
|
topicController.setProperties({
|
||||||
'model.currentPost': closest,
|
'model.currentPost': closest,
|
||||||
enteredAt: new Date().getTime().toString(),
|
enteredAt: new Date().getTime().toString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
topicProgressController.setProperties({
|
|
||||||
progressPosition: progress,
|
|
||||||
expanded: false
|
|
||||||
});
|
|
||||||
|
|
||||||
// Highlight our post after the next render
|
// Highlight our post after the next render
|
||||||
Ember.run.scheduleOnce('afterRender', function() {
|
Ember.run.scheduleOnce('afterRender', function() {
|
||||||
self.appEvents.trigger('post:highlight', closest);
|
self.appEvents.trigger('post:highlight', closest);
|
||||||
|
|
|
@ -210,8 +210,6 @@ const TopicRoute = Discourse.Route.extend({
|
||||||
this.topicTrackingState.trackIncoming('all');
|
this.topicTrackingState.trackIncoming('all');
|
||||||
controller.subscribe();
|
controller.subscribe();
|
||||||
|
|
||||||
this.controllerFor('topic-progress').set('model', model);
|
|
||||||
|
|
||||||
// We reset screen tracking every time a topic is entered
|
// We reset screen tracking every time a topic is entered
|
||||||
this.screenTrack.start(model.get('id'), controller);
|
this.screenTrack.start(model.get('id'), controller);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<nav id='topic-progress' title="{{i18n 'topic.progress.title'}}" class="{{if hideProgress 'hidden'}}">
|
<nav id='topic-progress' title="{{i18n 'topic.progress.title'}}" class="{{if hideProgress 'hidden'}}">
|
||||||
<div class='nums'>
|
<div class='nums'>
|
||||||
<h4>{{progressPosition}}</h4><span class="{{if hugeNumberOfPosts 'hidden'}}"> <span>/</span> <h4>{{model.postStream.filteredPostsCount}}</h4></span>
|
<h4>{{progressPosition}}</h4><span class="{{if hugeNumberOfPosts 'hidden'}}">
|
||||||
|
<span>/</span>
|
||||||
|
<h4>{{postStream.filteredPostsCount}}</h4></span>
|
||||||
</div>
|
</div>
|
||||||
<i class="fa {{unless expanded 'fa-sort'}}"></i>
|
<i class="fa {{unless expanded 'fa-sort'}}"></i>
|
||||||
<div class='bg'> </div>
|
<div class='bg'> </div>
|
|
@ -71,7 +71,10 @@
|
||||||
<section class="topic-area" id="topic" data-topic-id="{{unbound model.id}}">
|
<section class="topic-area" id="topic" data-topic-id="{{unbound model.id}}">
|
||||||
<div class="posts-wrapper">
|
<div class="posts-wrapper">
|
||||||
|
|
||||||
{{render "topic-progress"}}
|
{{topic-progress topic=model
|
||||||
|
progressPosition=progressPosition
|
||||||
|
jumpTop="jumpTop"
|
||||||
|
jumpBottom="jumpBottom"}}
|
||||||
|
|
||||||
{{conditional-loading-spinner condition=model.postStream.loadingAbove}}
|
{{conditional-loading-spinner condition=model.postStream.loadingAbove}}
|
||||||
|
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
export default Ember.View.extend({
|
|
||||||
elementId: 'topic-progress-wrapper',
|
|
||||||
docked: false,
|
|
||||||
classNameBindings: ['docked'],
|
|
||||||
|
|
||||||
_inserted: function() {
|
|
||||||
this.appEvents.on("composer:opened", this, '_dock')
|
|
||||||
.on("composer:resized", this, '_dock')
|
|
||||||
.on("composer:closed", this, '_dock')
|
|
||||||
.on("topic:scrolled", this, '_dock');
|
|
||||||
|
|
||||||
// Reflows are expensive. Cache the jQuery selector
|
|
||||||
// and the width when inserted into the DOM
|
|
||||||
this._$topicProgress = this.$('#topic-progress');
|
|
||||||
}.on('didInsertElement'),
|
|
||||||
|
|
||||||
_unbindEvents: function() {
|
|
||||||
this.appEvents.off("composer:opened", this, '_dock')
|
|
||||||
.off("composer:resized", this, '_dock')
|
|
||||||
.off("composer:closed", this, '_dock')
|
|
||||||
.off('topic:scrolled', this, '_dock');
|
|
||||||
}.on('willDestroyElement'),
|
|
||||||
|
|
||||||
_updateBar: function() {
|
|
||||||
Em.run.scheduleOnce('afterRender', this, '_updateProgressBar');
|
|
||||||
}.observes('controller.streamPercentage', 'controller.model.postStream.stream.[]').on('init'),
|
|
||||||
|
|
||||||
_updateProgressBar: function() {
|
|
||||||
// speeds up stuff, bypass jquery slowness and extra checks
|
|
||||||
if (!this._totalWidth) {
|
|
||||||
this._totalWidth = this._$topicProgress[0].offsetWidth;
|
|
||||||
}
|
|
||||||
const totalWidth = this._totalWidth;
|
|
||||||
const progressWidth = this.get('controller.streamPercentage') * totalWidth;
|
|
||||||
|
|
||||||
this._$topicProgress.find('.bg')
|
|
||||||
.css("border-right-width", (progressWidth === totalWidth) ? "0px" : "1px")
|
|
||||||
.width(progressWidth);
|
|
||||||
},
|
|
||||||
|
|
||||||
_dock() {
|
|
||||||
const maximumOffset = $('#topic-footer-buttons').offset(),
|
|
||||||
composerHeight = $('#reply-control').height() || 0,
|
|
||||||
$topicProgressWrapper = this.$(),
|
|
||||||
style = $topicProgressWrapper.attr('style') || '',
|
|
||||||
offset = window.pageYOffset || $('html').scrollTop();
|
|
||||||
|
|
||||||
let isDocked = false;
|
|
||||||
if (maximumOffset) {
|
|
||||||
const threshold = maximumOffset.top,
|
|
||||||
windowHeight = $(window).height(),
|
|
||||||
topicProgressHeight = $('#topic-progress').height();
|
|
||||||
|
|
||||||
isDocked = offset >= threshold - windowHeight + topicProgressHeight + composerHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (composerHeight > 0) {
|
|
||||||
if (isDocked) {
|
|
||||||
if (style.indexOf('bottom') >= 0) {
|
|
||||||
$topicProgressWrapper.css('bottom', '');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const height = composerHeight + "px";
|
|
||||||
if ($topicProgressWrapper.css('bottom') !== height) {
|
|
||||||
$topicProgressWrapper.css('bottom', height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (style.indexOf('bottom') >= 0) {
|
|
||||||
$topicProgressWrapper.css('bottom', '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.set('docked', isDocked);
|
|
||||||
},
|
|
||||||
|
|
||||||
_focusWhenOpened: function() {
|
|
||||||
|
|
||||||
// Don't focus on mobile or touch
|
|
||||||
if (this.site.mobileView || this.capabilities.isIOS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.get('controller.expanded')) {
|
|
||||||
const self = this;
|
|
||||||
Em.run.schedule('afterRender', function() {
|
|
||||||
self.$('input').focus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}.observes('controller.expanded'),
|
|
||||||
|
|
||||||
click(e) {
|
|
||||||
if ($(e.target).parents('#topic-progress').length) {
|
|
||||||
this.get('controller').send('toggleExpansion');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
keyDown(e) {
|
|
||||||
const controller = this.get('controller');
|
|
||||||
if (controller.get('expanded')) {
|
|
||||||
if (e.keyCode === 13) {
|
|
||||||
this.$('input').blur();
|
|
||||||
controller.send('jumpPost');
|
|
||||||
} else if (e.keyCode === 27) {
|
|
||||||
controller.send('toggleExpansion');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
|
@ -2,7 +2,7 @@ import { blank, present } from 'helpers/qunit-helpers';
|
||||||
|
|
||||||
moduleFor('controller:topic', 'controller:topic', {
|
moduleFor('controller:topic', 'controller:topic', {
|
||||||
needs: ['controller:modal', 'controller:composer', 'controller:quote-button',
|
needs: ['controller:modal', 'controller:composer', 'controller:quote-button',
|
||||||
'controller:topic-progress', 'controller:application']
|
'controller:application']
|
||||||
});
|
});
|
||||||
|
|
||||||
import Topic from 'discourse/models/topic';
|
import Topic from 'discourse/models/topic';
|
||||||
|
|
Loading…
Reference in a new issue