git ssb

10+

Matt McKegg / patchwork



Tree: 8bafac31ed8088c572b22263835ef43e71ffc34e

Files: 8bafac31ed8088c572b22263835ef43e71ffc34e / lib / scroller.js

2208 bytesRaw
1var pull = require('pull-stream')
2var Pause = require('pull-pause')
3var Value = require('mutant/value')
4var onceIdle = require('mutant/once-idle')
5var computed = require('mutant/computed')
6
7module.exports = Scroller
8
9function Scroller (scroller, content, render, opts) {
10 if (typeof opts === 'function') {
11 opts = {onDone: opts}
12 } else if (!opts) {
13 opts = {}
14 }
15 var toRenderCount = Value(0)
16 var toAppendCount = Value(0)
17 var pendingVisible = new Set()
18
19 var queueLength = computed([toRenderCount, toAppendCount], (a, b) => a + b)
20
21 var pause = Pause(function () {})
22 var running = true
23 var appendQueue = []
24
25 function appendLoop () {
26 var distanceFromBottom = scroller.scrollHeight - (scroller.scrollTop + scroller.clientHeight)
27 if (distanceFromBottom < scroller.clientHeight) {
28 while (appendQueue.length) {
29 var element = appendQueue.shift()
30 content.appendChild(element)
31 pendingVisible.add(element)
32 }
33 }
34
35 toAppendCount.set(appendQueue.length)
36 if (queueLength() < 5) {
37 // queue running low, resume stream
38 pause.resume()
39 }
40
41 if (running || queueLength()) {
42 window.requestAnimationFrame(appendLoop)
43 }
44 }
45
46 var stream = pull(
47 pause,
48 pull.drain(function (msg) {
49 toRenderCount.set(toRenderCount() + 1)
50
51 onceIdle(() => {
52 var element = render(msg)
53 appendQueue.push(element)
54 toRenderCount.set(toRenderCount() - 1)
55 })
56
57 if (queueLength() > 5) {
58 pause.pause()
59 }
60 }, function (err) {
61 running = false
62 clearInterval(visibleInterval)
63 opts.onDone ? opts.onDone(err) : console.error(err)
64 })
65 )
66
67 var visibleInterval = setInterval(() => {
68 // check for visible items every 2 seconds
69 Array.from(pendingVisible).forEach(checkVisible)
70 }, 2000)
71
72 stream.queue = queueLength
73
74 appendLoop()
75 return stream
76
77 function checkVisible (element) {
78 var height = scroller.clientHeight
79 var rect = element.getBoundingClientRect()
80 if (height > 50 && rect.bottom < height) {
81 pendingVisible.delete(element)
82 if (opts.onItemVisible) {
83 onceIdle(() => opts.onItemVisible(element))
84 }
85 }
86 }
87}
88

Built with git-ssb-web