preload content in CW (#110)

* preload content in CW

Fixes #63

* fix test
This commit is contained in:
Nolan Lawson 2018-04-14 10:47:53 -07:00 committed by GitHub
parent 707e89e899
commit ff8e92df6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 9 deletions

View file

@ -23,9 +23,9 @@
:originalStatus :uuid :spoilerShown :originalStatus :uuid :spoilerShown
on:recalculateHeight /> on:recalculateHeight />
{{/if}} {{/if}}
{{#if !spoilerText || spoilerShown}} {{#if showContent || contentPreloaded}}
<StatusContent :isStatusInOwnThread :isStatusInNotification <StatusContent :isStatusInOwnThread :isStatusInNotification
:originalStatus :uuid /> :originalStatus :uuid shown="{{showContent}}"/>
{{/if}} {{/if}}
{{#if originalStatus.media_attachments && originalStatus.media_attachments.length}} {{#if originalStatus.media_attachments && originalStatus.media_attachments.length}}
<StatusMediaAttachments :originalStatus :uuid <StatusMediaAttachments :originalStatus :uuid
@ -114,6 +114,7 @@
import { registerClickDelegate, unregisterClickDelegate } from '../../_utils/delegate' import { registerClickDelegate, unregisterClickDelegate } from '../../_utils/delegate'
import { classname } from '../../_utils/classname' import { classname } from '../../_utils/classname'
import { checkDomAncestors } from '../../_utils/checkDomAncestors' import { checkDomAncestors } from '../../_utils/checkDomAncestors'
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
const INPUT_TAGS = new Set(['a', 'button', 'input', 'textarea']) const INPUT_TAGS = new Set(['a', 'button', 'input', 'textarea'])
const isUserInputElement = node => INPUT_TAGS.has(node.localName) const isUserInputElement = node => INPUT_TAGS.has(node.localName)
@ -127,6 +128,13 @@
// the whole <article> is clickable in this case // the whole <article> is clickable in this case
registerClickDelegate(delegateKey, (e) => this.onClickOrKeydown(e)) registerClickDelegate(delegateKey, (e) => this.onClickOrKeydown(e))
} }
if (!this.get('showContent')) {
scheduleIdleTask(() => {
// Perf optimization: lazily load the StatusContent when the user is idle so that
// it's fast when they click the "show more" button
this.set({contentPreloaded: true})
})
}
}, },
ondestroy() { ondestroy() {
let delegateKey = this.get('delegateKey') let delegateKey = this.get('delegateKey')
@ -214,7 +222,8 @@
timelineType !== 'search' && 'status-in-timeline', timelineType !== 'search' && 'status-in-timeline',
isStatusInOwnThread && 'status-in-own-thread' isStatusInOwnThread && 'status-in-own-thread'
) )
} },
showContent: (spoilerText, spoilerShown) => !spoilerText || spoilerShown
} }
} }
</script> </script>

View file

@ -1,7 +1,4 @@
<div <div class="{{computedClass}}" ref:node>
class="status-content {{isStatusInOwnThread ? 'status-in-own-thread' : ''}} {{isStatusInNotification ? 'status-in-notification' : ''}}"
ref:node
>
{{{massagedContent}}} {{{massagedContent}}}
</div> </div>
<style> <style>
@ -12,6 +9,7 @@
overflow: hidden; overflow: hidden;
white-space: pre-wrap; white-space: pre-wrap;
font-size: 0.9em; font-size: 0.9em;
display: none;
} }
.status-content.status-in-own-thread { .status-content.status-in-own-thread {
@ -19,6 +17,10 @@
margin: 20px 10px 20px 5px; margin: 20px 10px 20px 5px;
} }
.status-content.shown {
display: block;
}
:global(.status-content .status-emoji) { :global(.status-content .status-emoji) {
width: 20px; width: 20px;
height: 20px; height: 20px;
@ -59,6 +61,7 @@
import { replaceAll } from '../../_utils/strings' import { replaceAll } from '../../_utils/strings'
import { mark, stop } from '../../_utils/marks' import { mark, stop } from '../../_utils/marks'
import { store } from '../../_store/store' import { store } from '../../_store/store'
import { classname } from '../../_utils/classname'
export default { export default {
oncreate() { oncreate() {
@ -66,6 +69,14 @@
}, },
store: () => store, store: () => store,
computed: { computed: {
computedClass: (isStatusInOwnThread, isStatusInNotification, shown) => {
return classname(
'status-content',
isStatusInOwnThread && 'status-in-own-thread',
isStatusInNotification && 'status-in-notification',
shown && 'shown'
)
},
massagedContent: (originalStatus, $autoplayGifs) => { massagedContent: (originalStatus, $autoplayGifs) => {
let content = originalStatus.content let content = originalStatus.content
// emojify // emojify

View file

@ -17,7 +17,7 @@ test('content warnings are posted', async t => {
.click(getNthShowOrHideButton(0)) .click(getNthShowOrHideButton(0))
.expect(getNthStatus(0).find('.status-content').innerText).contains('hello this is a toot') .expect(getNthStatus(0).find('.status-content').innerText).contains('hello this is a toot')
.click(getNthShowOrHideButton(0)) .click(getNthShowOrHideButton(0))
.expect(getNthStatus(0).find('.status-content').exists).notOk() .expect(getNthStatus(0).innerText).notContains('hello this is a toot')
}) })
test('content warnings are not posted if removed', async t => { test('content warnings are not posted if removed', async t => {
@ -28,6 +28,7 @@ test('content warnings are not posted if removed', async t => {
.click(contentWarningButton) .click(contentWarningButton)
.expect(composeContentWarning.exists).notOk() .expect(composeContentWarning.exists).notOk()
.click(composeButton) .click(composeButton)
.expect(getNthStatus(0).find('.status-spoiler').exists).notOk({timeout: 30000}) .expect(getNthStatus(0).innerText).contains('hi this is another toot', {timeout: 30000})
.expect(getNthStatus(0).innerText).notContains('content warning!')
.expect(getNthStatus(0).find('.status-content').innerText).contains('hi this is another toot') .expect(getNthStatus(0).find('.status-content').innerText).contains('hi this is another toot')
}) })