UX: Allow the timeline to scroll mid post

This commit is contained in:
Robin Ward 2016-05-26 16:23:47 -04:00
parent f8e6d05b8d
commit a3907e1fbb
No known key found for this signature in database
GPG Key ID: 0E091E2B4ED1B83D
7 changed files with 42 additions and 14 deletions

View File

@ -27,8 +27,9 @@ export default MountWidget.extend({
widget: 'post-stream', widget: 'post-stream',
_topVisible: null, _topVisible: null,
_bottomVisible: null, _bottomVisible: null,
_currentPost: -1, _currentPost: null,
_currentVisible: null, _currentVisible: null,
_currentPercent: null,
buildArgs() { buildArgs() {
return this.getProperties('posts', return this.getProperties('posts',
@ -82,13 +83,20 @@ export default MountWidget.extend({
if (windowBottom > bodyHeight) { windowBottom = bodyHeight; } if (windowBottom > bodyHeight) { windowBottom = bodyHeight; }
if (viewportBottom > bodyHeight) { viewportBottom = bodyHeight; } if (viewportBottom > bodyHeight) { viewportBottom = bodyHeight; }
let currentPost = -1; let currentPost = null;
let percent = null;
const offset = offsetCalculator(); const offset = offsetCalculator();
const topCheck = Math.ceil(windowTop + offset);
if (windowTop < offset) { if (windowTop < offset) {
currentPost = 0; 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; let bottomView = topView;
while (bottomView < $posts.length) { while (bottomView < $posts.length) {
const post = $posts[bottomView]; const post = $posts[bottomView];
@ -97,7 +105,8 @@ export default MountWidget.extend({
if (!$post) { break; } if (!$post) { break; }
const viewTop = $post.offset().top; const viewTop = $post.offset().top;
const viewBottom = viewTop + $post.height() + 100; const postHeight = $post.height();
const viewBottom = viewTop + postHeight;
if (viewTop > viewportBottom) { break; } if (viewTop > viewportBottom) { break; }
@ -105,7 +114,8 @@ export default MountWidget.extend({
onscreen.push(bottomView); onscreen.push(bottomView);
} }
if (currentPost === -1 && (viewTop >= windowTop + offset)) { if (currentPost === null && (viewTop <= topCheck) && (viewBottom > topCheck)) {
percent = (topCheck - viewTop) / postHeight;
currentPost = bottomView; currentPost = bottomView;
} }
@ -153,10 +163,16 @@ export default MountWidget.extend({
this.sendAction('currentPostChanged', { post }); this.sendAction('currentPostChanged', { post });
} }
if (percent !== null && this._currentPercent !== percent) {
this._currentPercent = percent;
this.sendAction('currentPostScrolled', { percent });
}
} else { } else {
this._topVisible = null; this._topVisible = null;
this._bottomVisible = null; this._bottomVisible = null;
this._currentPost = -1; this._currentPost = null;
this._currentPercent = null;
} }
const onscreenPostNumbers = []; const onscreenPostNumbers = [];

View File

@ -49,11 +49,11 @@ export default MountWidget.extend(Docking, {
didInsertElement() { didInsertElement() {
this._super(); this._super();
this.dispatch('topic:current-post-changed', 'timeline-scrollarea'); this.dispatch('topic:current-post-scrolled', 'timeline-scrollarea');
}, },
willDestroyElement() { willDestroyElement() {
this._super(); this._super();
this.appEvents.off('topic:current-post-changed'); this.appEvents.off('topic:current-post-scrolled');
} }
}); });

View File

@ -22,6 +22,7 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
enteredIndex: null, enteredIndex: null,
retrying: false, retrying: false,
userTriggeredProgress: null, userTriggeredProgress: null,
_progressIndex: null,
topicDelegated: [ topicDelegated: [
'toggleMultiSelect', 'toggleMultiSelect',
@ -204,7 +205,15 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
const postStream = model.get('postStream'); 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. // Called the the topmost visible post on the page changes.

View File

@ -8,7 +8,7 @@ export default Ember.Mixin.create({
init() { init() {
this._super(); this._super();
this.queueDockCheck = () => { this.queueDockCheck = () => {
Ember.run.debounce(this, this.dockCheck, helper, 20); Ember.run.debounce(this, this.dockCheck, helper, 5);
}; };
}, },

View File

@ -117,6 +117,7 @@
showInvite="showInvite" showInvite="showInvite"
topVisibleChanged="topVisibleChanged" topVisibleChanged="topVisibleChanged"
currentPostChanged="currentPostChanged" currentPostChanged="currentPostChanged"
currentPostScrolled="currentPostScrolled"
bottomVisibleChanged="bottomVisibleChanged" bottomVisibleChanged="bottomVisibleChanged"
selectPost="toggledSelectedPost" selectPost="toggledSelectedPost"
selectReplies="toggledSelectedPostReplies" selectReplies="toggledSelectedPostReplies"

View File

@ -96,7 +96,7 @@ createWidget('timeline-scrollarea', {
const topic = attrs.topic; const topic = attrs.topic;
const postStream = topic.get('postStream'); const postStream = topic.get('postStream');
const total = postStream.get('filteredPostsCount'); const total = postStream.get('filteredPostsCount');
let current = Math.round(total * percentage); let current = Math.floor(total * percentage);
if (current < 1) { current = 1; } if (current < 1) { current = 1; }
if (current > total) { current = total; } if (current > total) { current = total; }
@ -167,11 +167,11 @@ createWidget('timeline-scrollarea', {
this.sendWidgetAction('jumpToIndex', position.current); 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 the post number didn't change keep our scroll position
if (postNumber !== this.state.scrolledPost) { this.state.percentage = this._percentFor(this.attrs.topic, parseFloat(postNumber) + percent);
this.state.percentage = this._percentFor(this.attrs.topic, postNumber);
}
}, },
_percentFor(topic, postNumber) { _percentFor(topic, postNumber) {

View File

@ -42,6 +42,8 @@
</head> </head>
<body> <body>
<div class='debug-eyeline'></div>
<noscript data-path="<%= request.env['PATH_INFO'] %>"> <noscript data-path="<%= request.env['PATH_INFO'] %>">
<%= render partial: 'header' %> <%= render partial: 'header' %>
<div id="main-outlet" class="wrap"> <div id="main-outlet" class="wrap">