UX: Allow the timeline to scroll mid post
This commit is contained in:
parent
f8e6d05b8d
commit
a3907e1fbb
|
@ -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 = [];
|
||||||
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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">
|
||||||
|
|
Loading…
Reference in New Issue