From cc5ca90ac6234483bf3ebf0522df4455cdb044fe Mon Sep 17 00:00:00 2001 From: Robin Ward <robin.ward@gmail.com> Date: Wed, 24 Feb 2016 17:15:25 -0500 Subject: [PATCH] Cloak posts as they scroll off the screen for memory reasons --- .../components/scrolling-post-stream.js.es6 | 26 +++++++++++++---- .../discourse/widgets/post-stream.js.es6 | 28 +++++++++++++++++-- 2 files changed, 47 insertions(+), 7 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 b18152e8c..032a08c45 100644 --- a/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 +++ b/app/assets/javascripts/discourse/components/scrolling-post-stream.js.es6 @@ -1,6 +1,7 @@ import DiscourseURL from 'discourse/lib/url'; import { keyDirty } from 'discourse/widgets/widget'; import MountWidget from 'discourse/components/mount-widget'; +import { cloak, uncloak } from 'discourse/widgets/post-stream'; function findTopView($posts, viewportTop, min, max) { if (max < min) { return min; } @@ -45,7 +46,7 @@ export default MountWidget.extend({ let windowTop = $w.scrollTop(); - const $posts = this.$('.onscreen-post'); + const $posts = this.$('.onscreen-post, .cloaked-post'); const viewportTop = windowTop - slack; const topView = findTopView($posts, viewportTop, 0, $posts.length-1); @@ -64,7 +65,7 @@ export default MountWidget.extend({ if (!$post) { break; } const viewTop = $post.offset().top; - const viewBottom = viewTop + $post.height(); + const viewBottom = viewTop + $post.height() + 100; if (viewTop > viewportBottom) { break; } @@ -76,9 +77,8 @@ export default MountWidget.extend({ } const posts = this.posts; + const refresh = cb => this.queueRerender(cb); if (onscreen.length) { - - const refresh = cb => this.queueRerender(cb); const first = posts.objectAt(onscreen[0]); if (this._topVisible !== first) { this._topVisible = first; @@ -113,7 +113,21 @@ export default MountWidget.extend({ this._bottomVisible = null; } - const onscreenPostNumbers = onscreen.map(idx => posts.objectAt(idx).post_number); + const onscreenPostNumbers = []; + const prev = this._previouslyOnscreen; + const newPrev = {}; + onscreen.forEach(idx => { + const post = posts.objectAt(idx); + const postNumber = post.post_number; + delete prev[postNumber]; + onscreenPostNumbers.push(postNumber); + newPrev[postNumber] = post; + uncloak(post, this); + }); + + Object.keys(prev).forEach(pn => cloak(prev[pn], this)); + + this._previouslyOnscreen = newPrev; this.screenTrack.setOnscreen(onscreenPostNumbers); }, @@ -125,6 +139,8 @@ export default MountWidget.extend({ this._super(); const debouncedScroll = () => Ember.run.debounce(this, this._scrollTriggered, 10); + this._previouslyOnscreen = {}; + this.appEvents.on('post-stream:refresh', debouncedScroll); $(document).bind('touchmove.post-stream', debouncedScroll); $(window).bind('scroll.post-stream', debouncedScroll); diff --git a/app/assets/javascripts/discourse/widgets/post-stream.js.es6 b/app/assets/javascripts/discourse/widgets/post-stream.js.es6 index f7fb75e14..9eddc3b5d 100644 --- a/app/assets/javascripts/discourse/widgets/post-stream.js.es6 +++ b/app/assets/javascripts/discourse/widgets/post-stream.js.es6 @@ -1,9 +1,30 @@ import { createWidget } from 'discourse/widgets/widget'; import transformPost from 'discourse/lib/transform-post'; import { Placeholder } from 'discourse/lib/posts-with-placeholders'; +import { h } from 'virtual-dom'; +import { addWidgetCleanCallback } from 'discourse/components/mount-widget'; +const CLOAKING_ENABLED = true; const DAY = 1000 * 60 * 60 * 24; +let _cloaked = {}; + +export function cloak(post, component) { + if (!CLOAKING_ENABLED || _cloaked[post.id]) { return; } + + const $post = $(`#post_${post.post_number}`); + _cloaked[post.id] = $post.height(); + Ember.run.debounce(component, 'queueRerender', 1000); +} + +export function uncloak(post, component) { + if (!CLOAKING_ENABLED || !_cloaked[post.id]) { return; } + _cloaked[post.id] = null; + component.queueRerender(); +} + +addWidgetCleanCallback('post-stream', () => _cloaked = {}); + export default createWidget('post-stream', { tagName: 'div.post-stream', @@ -63,8 +84,11 @@ export default createWidget('post-stream', { } prevDate = curTime; - // actual post contents - if (transformed.isSmallAction) { + const height = _cloaked[post.id]; + if (height) { + result.push(h('div.cloaked-post', { id: `post_${post.post_number}`, + attributes: { style: `height: ${height}px` } })); + } else if (transformed.isSmallAction) { result.push(this.attach('post-small-action', transformed, { model: post })); } else { result.push(this.attach('post', transformed, { model: post }));