diff --git a/routes/_components/status/Notification.html b/routes/_components/status/Notification.html index 10b8bf1b..93c57ae5 100644 --- a/routes/_components/status/Notification.html +++ b/routes/_components/status/Notification.html @@ -42,7 +42,8 @@ export default { oncreate() { let focusSelector = this.get('focusSelector') - if (this.refs.node && focusSelector) { + if (this.refs.node && focusSelector && + this.store.getForCurrentTimeline('shouldRestoreFocus')) { restoreFocus(this.refs.node, focusSelector) } }, diff --git a/routes/_components/status/Status.html b/routes/_components/status/Status.html index 0d1f2527..94493d4c 100644 --- a/routes/_components/status/Status.html +++ b/routes/_components/status/Status.html @@ -113,7 +113,8 @@ registerClickDelegate(delegateKey, (e) => this.onClickOrKeydown(e)) } let focusSelector = this.get('focusSelector') - if (this.refs.node && focusSelector) { + if (this.refs.node && focusSelector && + this.store.getForCurrentTimeline('shouldRestoreFocus')) { restoreFocus(this.refs.node, focusSelector) } }, diff --git a/routes/_components/timeline/Timeline.html b/routes/_components/timeline/Timeline.html index c9782d48..412483dd 100644 --- a/routes/_components/timeline/Timeline.html +++ b/routes/_components/timeline/Timeline.html @@ -177,6 +177,16 @@ }, onScrollTopChanged(scrollTop) { this.set({scrollTop: scrollTop}) + if (!this.get('observedOnScrollTopChanged')) { + // ignore the first scroll top change, e.g. + // because we forced a scroll top change + this.set({observedOnScrollTopChanged: true}) + } else { + // after that, don't allow statuses/notifications to call focus() + // after we've already started scrolling. that causes scrolling to + // jump around + this.store.setForCurrentTimeline({shouldRestoreFocus: false}) + } }, onScrollToBottom() { if (!this.store.get('initialized') || @@ -233,7 +243,10 @@ }, setupFocus() { this.onPushState = this.onPushState.bind(this) - this.store.setForCurrentTimeline({ignoreBlurEvents: false}) + this.store.setForCurrentTimeline({ + ignoreBlurEvents: false, + shouldRestoreFocus: true + }) window.addEventListener('pushState', this.onPushState) }, teardownFocus() { diff --git a/routes/_store/computations/timelineComputations.js b/routes/_store/computations/timelineComputations.js index 47990143..c299fe3c 100644 --- a/routes/_store/computations/timelineComputations.js +++ b/routes/_store/computations/timelineComputations.js @@ -18,6 +18,7 @@ export function timelineComputations (store) { computeForTimeline(store, 'showHeader', false) computeForTimeline(store, 'shouldShowHeader', false) computeForTimeline(store, 'timelineItemIdsAreStale', false) + computeForTimeline(store, 'shouldRestoreFocus', false) store.compute('firstTimelineItemId', ['timelineItemIds'], (timelineItemIds) => { return timelineItemIds && timelineItemIds[0] diff --git a/routes/_store/mixins/timelineMixins.js b/routes/_store/mixins/timelineMixins.js index d965e283..f2d73d69 100644 --- a/routes/_store/mixins/timelineMixins.js +++ b/routes/_store/mixins/timelineMixins.js @@ -20,6 +20,12 @@ export function timelineMixins (Store) { return root && root[instanceName] && root[instanceName][timelineName] } + Store.prototype.getForCurrentTimeline = function (key) { + let instanceName = this.get('currentInstance') + let timelineName = this.get('currentTimeline') + return this.getForTimeline(instanceName, timelineName, key) + } + Store.prototype.getAllTimelineData = function (instanceName, key) { let root = this.get(`timelineData_${key}`) || {} return root[instanceName] || {}