From a3907e1fbbe5bc63696f994739e6575e9784fb11 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Thu, 26 May 2016 16:23:47 -0400 Subject: [PATCH] UX: Allow the timeline to scroll mid post --- .../components/scrolling-post-stream.js.es6 | 26 +++++++++++++++---- .../components/topic-timeline.js.es6 | 4 +-- .../discourse/controllers/topic.js.es6 | 11 +++++++- .../discourse/mixins/docking.js.es6 | 2 +- .../javascripts/discourse/templates/topic.hbs | 1 + .../discourse/widgets/topic-timeline.js.es6 | 10 +++---- app/views/layouts/application.html.erb | 2 ++ 7 files changed, 42 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 b/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 index cfbcb5ffae1..a684fea4b5b 100644 --- a/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 +++ b/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 @@ -27,8 +27,9 @@ export default MountWidget.extend({ widget: 'post-stream', _topVisible: null, _bottomVisible: null, - _currentPost: -1, + _currentPost: null, _currentVisible: null, + _currentPercent: null, buildArgs() { return this.getProperties('posts', @@ -82,13 +83,20 @@ export default MountWidget.extend({ if (windowBottom > bodyHeight) { windowBottom = bodyHeight; } if (viewportBottom > bodyHeight) { viewportBottom = bodyHeight; } - let currentPost = -1; + let currentPost = null; + let percent = null; const offset = offsetCalculator(); + const topCheck = Math.ceil(windowTop + offset); if (windowTop < offset) { currentPost = 0; + const $post = $($posts[0]); + percent = windowTop > 0 ? (topCheck - $post.offset().top) / $post.height() : 0; } + // uncomment to debug the eyeline + // $('.debug-eyeline').css({ height: '1px', width: '100%', backgroundColor: 'blue', position: 'absolute', top: `${topCheck}px` }); + let bottomView = topView; while (bottomView < $posts.length) { const post = $posts[bottomView]; @@ -97,7 +105,8 @@ export default MountWidget.extend({ if (!$post) { break; } const viewTop = $post.offset().top; - const viewBottom = viewTop + $post.height() + 100; + const postHeight = $post.height(); + const viewBottom = viewTop + postHeight; if (viewTop > viewportBottom) { break; } @@ -105,7 +114,8 @@ export default MountWidget.extend({ onscreen.push(bottomView); } - if (currentPost === -1 && (viewTop >= windowTop + offset)) { + if (currentPost === null && (viewTop <= topCheck) && (viewBottom > topCheck)) { + percent = (topCheck - viewTop) / postHeight; currentPost = bottomView; } @@ -153,10 +163,16 @@ export default MountWidget.extend({ this.sendAction('currentPostChanged', { post }); } + if (percent !== null && this._currentPercent !== percent) { + this._currentPercent = percent; + this.sendAction('currentPostScrolled', { percent }); + } + } else { this._topVisible = null; this._bottomVisible = null; - this._currentPost = -1; + this._currentPost = null; + this._currentPercent = null; } const onscreenPostNumbers = []; diff --git a/app/assets/javascripts/discourse/components/topic-timeline.js.es6 b/app/assets/javascripts/discourse/components/topic-timeline.js.es6 index 2e7e5c09676..e27f74f8a01 100644 --- a/app/assets/javascripts/discourse/components/topic-timeline.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-timeline.js.es6 @@ -49,11 +49,11 @@ export default MountWidget.extend(Docking, { didInsertElement() { this._super(); - this.dispatch('topic:current-post-changed', 'timeline-scrollarea'); + this.dispatch('topic:current-post-scrolled', 'timeline-scrollarea'); }, willDestroyElement() { this._super(); - this.appEvents.off('topic:current-post-changed'); + this.appEvents.off('topic:current-post-scrolled'); } }); diff --git a/app/assets/javascripts/discourse/controllers/topic.js.es6 b/app/assets/javascripts/discourse/controllers/topic.js.es6 index 89b4b22d815..102ef91a0ba 100644 --- a/app/assets/javascripts/discourse/controllers/topic.js.es6 +++ b/app/assets/javascripts/discourse/controllers/topic.js.es6 @@ -22,6 +22,7 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, { enteredIndex: null, retrying: false, userTriggeredProgress: null, + _progressIndex: null, topicDelegated: [ 'toggleMultiSelect', @@ -204,7 +205,15 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, { const postStream = model.get('postStream'); - this.appEvents.trigger('topic:current-post-changed', postStream.progressIndexOfPost(post)); + this._progressIndex = postStream.progressIndexOfPost(post); + this.appEvents.trigger('topic:current-post-changed', this._progressIndex); + }, + + currentPostScrolled(event) { + this.appEvents.trigger('topic:current-post-scrolled', { + postNumber: this._progressIndex, + percent: event.percent + }); }, // Called the the topmost visible post on the page changes. diff --git a/app/assets/javascripts/discourse/mixins/docking.js.es6 b/app/assets/javascripts/discourse/mixins/docking.js.es6 index ee024ed45e9..6d897ac1999 100644 --- a/app/assets/javascripts/discourse/mixins/docking.js.es6 +++ b/app/assets/javascripts/discourse/mixins/docking.js.es6 @@ -8,7 +8,7 @@ export default Ember.Mixin.create({ init() { this._super(); this.queueDockCheck = () => { - Ember.run.debounce(this, this.dockCheck, helper, 20); + Ember.run.debounce(this, this.dockCheck, helper, 5); }; }, diff --git a/app/assets/javascripts/discourse/templates/topic.hbs b/app/assets/javascripts/discourse/templates/topic.hbs index e1394f55047..b4ba09db5af 100644 --- a/app/assets/javascripts/discourse/templates/topic.hbs +++ b/app/assets/javascripts/discourse/templates/topic.hbs @@ -117,6 +117,7 @@ showInvite="showInvite" topVisibleChanged="topVisibleChanged" currentPostChanged="currentPostChanged" + currentPostScrolled="currentPostScrolled" bottomVisibleChanged="bottomVisibleChanged" selectPost="toggledSelectedPost" selectReplies="toggledSelectedPostReplies" diff --git a/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6 b/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6 index 8ad40c1f52f..c32db721f88 100644 --- a/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6 +++ b/app/assets/javascripts/discourse/widgets/topic-timeline.js.es6 @@ -96,7 +96,7 @@ createWidget('timeline-scrollarea', { const topic = attrs.topic; const postStream = topic.get('postStream'); const total = postStream.get('filteredPostsCount'); - let current = Math.round(total * percentage); + let current = Math.floor(total * percentage); if (current < 1) { current = 1; } if (current > total) { current = total; } @@ -167,11 +167,11 @@ createWidget('timeline-scrollarea', { this.sendWidgetAction('jumpToIndex', position.current); }, - topicCurrentPostChanged(postNumber) { + topicCurrentPostScrolled(event) { + const { postNumber, percent } = event; + // If the post number didn't change keep our scroll position - if (postNumber !== this.state.scrolledPost) { - this.state.percentage = this._percentFor(this.attrs.topic, postNumber); - } + this.state.percentage = this._percentFor(this.attrs.topic, parseFloat(postNumber) + percent); }, _percentFor(topic, postNumber) { diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ff7d545b579..93ec5c17a0a 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -42,6 +42,8 @@ +
+