FEATURE: show timeline component when expanding post progress
- Show fullscreen timeline with title of topic in mobile - Go to post # kb shortcut now unconditionally uses a modal - Always show wrench on topics (was missing if progress bar was showing) - Be smarter about rendering timeline even if composer is open (provided there is room)
This commit is contained in:
@@ -1,17 +1,65 @@
|
||||
import { observes } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
composerOpen: null,
|
||||
classNameBindings: ['composerOpen'],
|
||||
showTimeline: null,
|
||||
info: null,
|
||||
info: Em.Object.create(),
|
||||
|
||||
_checkSize() {
|
||||
const renderTimeline = $(window).width() > 960;
|
||||
this.set('info', { renderTimeline, showTimeline: renderTimeline && !this.get('composerOpen') });
|
||||
let info = this.get('info');
|
||||
|
||||
if (info.get('topicProgressExpanded')) {
|
||||
|
||||
info.setProperties({
|
||||
renderTimeline: true,
|
||||
renderAdminMenuButton: true
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
let renderTimeline = !this.site.mobileView;
|
||||
|
||||
if (renderTimeline) {
|
||||
|
||||
const width = $(window).width();
|
||||
let height = $(window).height();
|
||||
|
||||
if (this.get('composerOpen')) {
|
||||
height -= $('#reply-control').height();
|
||||
}
|
||||
|
||||
renderTimeline = width > 960 && height > 520;
|
||||
}
|
||||
|
||||
info.setProperties({
|
||||
renderTimeline,
|
||||
renderAdminMenuButton: !renderTimeline
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// we need to store this so topic progress has something to init with
|
||||
_topicScrolled(event) {
|
||||
this.set('info.prevEvent', event);
|
||||
},
|
||||
|
||||
@observes('info.topicProgressExpanded')
|
||||
_expanded() {
|
||||
if (this.get('info.topicProgressExpanded')) {
|
||||
$(window).on('click.hide-fullscreen', (e) => {
|
||||
if (!$(e.target).parents().is('.timeline-container, #topic-progress-wrapper')) {
|
||||
this._collapseFullscreen();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$(window).off('click.hide-fullscreen');
|
||||
}
|
||||
this._checkSize();
|
||||
},
|
||||
|
||||
composerOpened() {
|
||||
this.set('composerOpen', true);
|
||||
this._checkSize();
|
||||
// we need to do the check after animation is done
|
||||
setTimeout(()=>this._checkSize(), 500);
|
||||
},
|
||||
|
||||
composerClosed() {
|
||||
@@ -19,25 +67,66 @@ export default Ember.Component.extend({
|
||||
this._checkSize();
|
||||
},
|
||||
|
||||
_collapseFullscreen() {
|
||||
if (this.get('info.topicProgressExpanded')) {
|
||||
$('.timeline-fullscreen').removeClass('show');
|
||||
setTimeout(() => {
|
||||
this.set('info.topicProgressExpanded', false);
|
||||
this._checkSize();
|
||||
},500);
|
||||
}
|
||||
},
|
||||
|
||||
keyboardTrigger(e) {
|
||||
if(e.type === "jump") {
|
||||
bootbox.prompt(I18n.t('topic.progress.jump_prompt_long'), postIndex => {
|
||||
if (postIndex === null) { return; }
|
||||
this.sendAction('jumpToIndex', postIndex);
|
||||
});
|
||||
|
||||
// this is insanely hacky, for some reason shown event never fires,
|
||||
// something is bust in bootbox
|
||||
// TODO upgrade bootbox to see if this hack can be removed
|
||||
setTimeout(()=>{
|
||||
$('.bootbox.modal').trigger('shown');
|
||||
},50);
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
|
||||
this.appEvents
|
||||
.on('topic:current-post-scrolled', this, this._topicScrolled)
|
||||
.on('topic:jump-to-post', this, this._collapseFullscreen)
|
||||
.on('topic:keyboard-trigger', this, this.keyboardTrigger);
|
||||
|
||||
if (!this.site.mobileView) {
|
||||
$(window).on('resize.discourse-topic-navigation', () => this._checkSize());
|
||||
this.appEvents.on('composer:will-open', this, this.composerOpened);
|
||||
this.appEvents.on('composer:will-close', this, this.composerClosed);
|
||||
this._checkSize();
|
||||
} else {
|
||||
this.set('info', null);
|
||||
$('#reply-control').on('div-resized.discourse-topic-navigation', () => this._checkSize());
|
||||
}
|
||||
|
||||
this._checkSize();
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this._super();
|
||||
|
||||
this.appEvents
|
||||
.off('topic:current-post-scrolled', this, this._topicScrolled)
|
||||
.off('topic:jump-to-post', this, this._collapseFullscreen)
|
||||
.off('topic:keyboard-trigger', this, this.keyboardTrigger);
|
||||
|
||||
$(window).off('click.hide-fullscreen');
|
||||
|
||||
if (!this.site.mobileView) {
|
||||
$(window).off('resize.discourse-topic-navigation');
|
||||
this.appEvents.off('composer:will-open', this, this.composerOpened);
|
||||
this.appEvents.off('composer:will-close', this, this.composerClosed);
|
||||
$('#reply-control').off('div-resized.discourse-topic-navigation');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2,13 +2,11 @@ import { default as computed, observes } from 'ember-addons/ember-computed-decor
|
||||
|
||||
export default Ember.Component.extend({
|
||||
elementId: 'topic-progress-wrapper',
|
||||
classNameBindings: ['docked', 'hidden'],
|
||||
classNameBindings: ['docked'],
|
||||
expanded: false,
|
||||
toPostIndex: null,
|
||||
docked: false,
|
||||
progressPosition: null,
|
||||
postStream: Ember.computed.alias('topic.postStream'),
|
||||
userWantsToJump: null,
|
||||
_streamPercentage: null,
|
||||
|
||||
init() {
|
||||
@@ -16,26 +14,6 @@ export default Ember.Component.extend({
|
||||
(this.get('delegated') || []).forEach(m => this.set(m, m));
|
||||
},
|
||||
|
||||
@computed('userWantsToJump', 'showTimeline')
|
||||
hidden(userWantsToJump, showTimeline) {
|
||||
return !userWantsToJump && showTimeline;
|
||||
},
|
||||
|
||||
@observes('hidden')
|
||||
visibilityChanged() {
|
||||
if (!this.get('hidden')) {
|
||||
this._updateBar();
|
||||
}
|
||||
},
|
||||
|
||||
keyboardTrigger(kbdEvent) {
|
||||
if (kbdEvent.type === 'jump') {
|
||||
this.set('expanded', true);
|
||||
this.set('userWantsToJump', true);
|
||||
Ember.run.scheduleOnce('afterRender', () => this.$('.jump-form input').focus());
|
||||
}
|
||||
},
|
||||
|
||||
@computed('progressPosition')
|
||||
jumpTopDisabled(progressPosition) {
|
||||
return progressPosition <= 3;
|
||||
@@ -83,10 +61,15 @@ export default Ember.Component.extend({
|
||||
.on("composer:resized", this, this._dock)
|
||||
.on('composer:closed', this, this._dock)
|
||||
.on("topic:scrolled", this, this._dock)
|
||||
.on('topic:current-post-scrolled', this, this._topicScrolled)
|
||||
.on('topic-progress:keyboard-trigger', this, this.keyboardTrigger);
|
||||
.on('topic:current-post-scrolled', this, this._topicScrolled);
|
||||
|
||||
Ember.run.scheduleOnce('afterRender', this, this._updateProgressBar);
|
||||
const prevEvent = this.get('prevEvent');
|
||||
if (prevEvent) {
|
||||
this._topicScrolled(prevEvent);
|
||||
} else {
|
||||
Ember.run.scheduleOnce('afterRender', this, this._updateProgressBar);
|
||||
}
|
||||
Ember.run.scheduleOnce('afterRender', this, this._dock);
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
@@ -95,12 +78,11 @@ export default Ember.Component.extend({
|
||||
.off("composer:resized", this, this._dock)
|
||||
.off('composer:closed', this, this._dock)
|
||||
.off('topic:scrolled', this, this._dock)
|
||||
.off('topic:current-post-scrolled', this, this._topicScrolled)
|
||||
.off('topic-progress:keyboard-trigger');
|
||||
.off('topic:current-post-scrolled', this, this._topicScrolled);
|
||||
},
|
||||
|
||||
_updateProgressBar() {
|
||||
if (this.isDestroyed || this.isDestroying || this.get('hidden')) { return; }
|
||||
if (this.isDestroyed || this.isDestroying) { return; }
|
||||
|
||||
const $topicProgress = this.$('#topic-progress');
|
||||
// speeds up stuff, bypass jquery slowness and extra checks
|
||||
@@ -127,6 +109,10 @@ export default Ember.Component.extend({
|
||||
offset = window.pageYOffset || $('html').scrollTop(),
|
||||
topicProgressHeight = $('#topic-progress').height();
|
||||
|
||||
if (!$topicProgressWrapper || $topicProgressWrapper.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let isDocked = false;
|
||||
if (maximumOffset) {
|
||||
const threshold = maximumOffset.top;
|
||||
@@ -156,71 +142,11 @@ export default Ember.Component.extend({
|
||||
}
|
||||
},
|
||||
|
||||
keyDown(e) {
|
||||
if (this.get('expanded')) {
|
||||
if (e.keyCode === 13) {
|
||||
this.$('input').blur();
|
||||
this.send('jumpPost');
|
||||
} else if (e.keyCode === 27) {
|
||||
this.send('toggleExpansion');
|
||||
this.set('userWantsToJump', false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_jumpTo(postIndex) {
|
||||
postIndex = parseInt(postIndex, 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);
|
||||
this._beforeJump();
|
||||
this.sendAction('jumpToIndex', postIndex);
|
||||
},
|
||||
|
||||
actions: {
|
||||
toggleExpansion(opts) {
|
||||
toggleExpansion() {
|
||||
this.toggleProperty('expanded');
|
||||
if (this.get('expanded')) {
|
||||
this.set('userWantsToJump', false);
|
||||
this.set('toPostIndex', this.get('progressPosition'));
|
||||
if (opts && opts.highlight) {
|
||||
Ember.run.next(() => $('.jump-form input').select().focus());
|
||||
}
|
||||
if (!this.site.mobileView && !this.capabilities.isIOS) {
|
||||
Ember.run.schedule('afterRender', () => this.$('input').focus());
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
jumpPrompt() {
|
||||
const postIndex = prompt(I18n.t('topic.progress.jump_prompt_long'));
|
||||
if (postIndex === null) { return; }
|
||||
this._jumpTo(postIndex);
|
||||
},
|
||||
|
||||
jumpPost() {
|
||||
this._jumpTo(this.get('toPostIndex'));
|
||||
},
|
||||
|
||||
jumpTop() {
|
||||
this._beforeJump();
|
||||
this.sendAction('jumpTop');
|
||||
},
|
||||
|
||||
jumpBottom() {
|
||||
this._beforeJump();
|
||||
this.sendAction('jumpBottom');
|
||||
}
|
||||
},
|
||||
|
||||
_beforeJump() {
|
||||
this.set('expanded', false);
|
||||
this.set('userWantsToJump', false);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,12 +10,28 @@ export default MountWidget.extend(Docking, {
|
||||
dockAt: null,
|
||||
|
||||
buildArgs() {
|
||||
return { topic: this.get('topic'),
|
||||
topicTrackingState: this.topicTrackingState,
|
||||
enteredIndex: this.get('enteredIndex'),
|
||||
dockAt: this.dockAt,
|
||||
top: this.dockAt || FIXED_POS,
|
||||
dockBottom: this.dockBottom };
|
||||
let attrs = {
|
||||
topic: this.get('topic'),
|
||||
topicTrackingState: this.topicTrackingState,
|
||||
enteredIndex: this.get('enteredIndex'),
|
||||
dockBottom: this.dockBottom,
|
||||
mobileView: this.get('site.mobileView')
|
||||
};
|
||||
|
||||
let event = this.get('prevEvent');
|
||||
if (event) {
|
||||
attrs.enteredIndex = event.postIndex-1;
|
||||
}
|
||||
|
||||
if (this.get('fullscreen')) {
|
||||
attrs.fullScreen = true;
|
||||
attrs.addShowClass = this.get('addShowClass');
|
||||
} else {
|
||||
attrs.dockAt = this.dockAt;
|
||||
attrs.top = this.dockAt || FIXED_POS;
|
||||
}
|
||||
|
||||
return attrs;
|
||||
},
|
||||
|
||||
@observes('topic.highest_post_number', 'loading')
|
||||
@@ -54,6 +70,14 @@ export default MountWidget.extend(Docking, {
|
||||
|
||||
didInsertElement() {
|
||||
this._super();
|
||||
|
||||
if (this.get('fullscreen') && !this.get('addShowClass')) {
|
||||
Em.run.next(()=>{
|
||||
this.set('addShowClass', true);
|
||||
this.queueRerender();
|
||||
});
|
||||
}
|
||||
|
||||
this.dispatch('topic:current-post-scrolled', 'timeline-scrollarea');
|
||||
this.dispatch('topic-notifications-button:keyboard-trigger', 'topic-notifications-button');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user