git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Commit cff270be8e13b929bbb91731f12bf29dfa001197

preserve unread flags on messages after refresh (if haven't scrolled past)

also match unread flag appearance in light and dark themes
Matt McKegg committed on 12/4/2017, 2:02:51 AM
Parent: 3ce9f274492ef4b74c0de22ed8b53fa746fe0c4d

Files changed

lib/scroller.jschanged
locales/en.jsonchanged
modules/feed/html/rollup.jschanged
plugs/message/html/layout/default.jschanged
styles/dark/feed-event.mcsschanged
styles/dark/message.mcsschanged
styles/light/feed-event.mcsschanged
styles/light/message.mcsschanged
lib/scroller.jsView
@@ -5,11 +5,17 @@
55 var computed = require('mutant/computed')
66
77 module.exports = Scroller
88
9-function Scroller (scroller, content, render, cb) {
9+function Scroller (scroller, content, render, opts) {
10+ if (typeof opts === 'function') {
11+ opts = {onDone: opts}
12+ } else if (!opts) {
13+ opts = {}
14+ }
1015 var toRenderCount = Value(0)
1116 var toAppendCount = Value(0)
17+ var pendingVisible = new Set()
1218
1319 var queueLength = computed([toRenderCount, toAppendCount], (a, b) => a + b)
1420
1521 var pause = Pause(function () {})
@@ -19,9 +25,11 @@
1925 function appendLoop () {
2026 var distanceFromBottom = scroller.scrollHeight - (scroller.scrollTop + scroller.clientHeight)
2127 if (distanceFromBottom < scroller.clientHeight) {
2228 while (appendQueue.length) {
23- content.appendChild(appendQueue.shift())
29+ var element = appendQueue.shift()
30+ content.appendChild(element)
31+ pendingVisible.add(element)
2432 }
2533 }
2634
2735 toAppendCount.set(appendQueue.length)
@@ -32,8 +40,9 @@
3240
3341 if (running || queueLength()) {
3442 window.requestAnimationFrame(appendLoop)
3543 }
44+
3645 }
3746
3847 var stream = pull(
3948 pause,
@@ -50,13 +59,30 @@
5059 pause.pause()
5160 }
5261 }, function (err) {
5362 running = false
54- cb ? cb(err) : console.error(err)
63+ clearInterval(visibleInterval)
64+ opts.onDone ? opts.onDone(err) : console.error(err)
5565 })
5666 )
5767
68+ var visibleInterval = setInterval(() => {
69+ // check for visible items every 2 seconds
70+ Array.from(pendingVisible).forEach(checkVisible)
71+ }, 2000)
72+
5873 stream.queue = queueLength
5974
6075 appendLoop()
6176 return stream
77+
78+ function checkVisible (element) {
79+ var height = scroller.clientHeight
80+ var rect = element.getBoundingClientRect()
81+ if (height > 50 && rect.bottom < height) {
82+ pendingVisible.delete(element)
83+ if (opts.onItemVisible) {
84+ onceIdle(() => opts.onItemVisible(element))
85+ }
86+ }
87+ }
6288 }
locales/en.jsonView
@@ -183,6 +183,7 @@
183183 "pt-BR": "Brazillian Portuguese",
184184 "See less": "See less",
185185 "See more": "See more",
186186 "(missing message)": "(missing message)",
187- "assigned a description to ": "assigned a description to "
187+ "assigned a description to ": "assigned a description to ",
188+ "Unread Message": "Unread Message"
188189 }
modules/feed/html/rollup.jsView
@@ -60,8 +60,9 @@
6060
6161 var abortLastFeed = null
6262 var content = Value()
6363 var loading = Proxy(true)
64+ var unreadIds = new Set()
6465 var newSinceRefresh = new Set()
6566 var highlightItems = new Set()
6667
6768 var container = h('Scroller', {
@@ -106,8 +107,9 @@
106107 // the feed as otherwise the 'show <n> updates message' will be
107108 // shown on new messages that patchwork cannot render
108109 if (canRenderMessage(msg) && (!msg.root || canRenderMessage(msg.root))) {
109110 newSinceRefresh.add(msg.key)
111+ unreadIds.add(msg.key)
110112 }
111113
112114 if (updates() === 0 && msg.value.author === yourId && container.scrollTop < 20) {
113115 refresh()
@@ -143,11 +145,22 @@
143145
144146 highlightItems = newSinceRefresh
145147 newSinceRefresh = new Set()
146148
149+ window.thing = unreadIds
150+
147151 var done = Value(false)
148152 var stream = nextStepper(getStream, {reverse: true, limit: 50})
149- var scroller = Scroller(container, content(), renderItem, () => done.set(true))
153+ var scroller = Scroller(container, content(), renderItem, {
154+ onDone: () => done.set(true),
155+ onItemVisible: (item) => {
156+ if (Array.isArray(item.msgIds)) {
157+ item.msgIds.forEach(id => {
158+ unreadIds.delete(id)
159+ })
160+ }
161+ }
162+ })
150163
151164 // track loading state
152165 loading.set(computed([done, scroller.queue], (done, queue) => {
153166 return !done && queue < 5
@@ -192,16 +205,17 @@
192205 }
193206 })
194207
195208 var replies = item.replies.filter(isReply).sort(byAssertedTime)
196- var highlightedReplies = replies.filter(isHighlighted)
209+ var highlightedReplies = replies.filter(getPriority)
197210 var replyElements = replies.filter(displayFilter).slice(-3).map((msg) => {
198211 var result = api.message.html.render(msg, {
199212 previousId,
200213 compact: compactFilter(msg, item),
201- priority: highlightItems.has(msg.key) ? 2 : 0
214+ priority: getPriority(msg)
202215 })
203216 previousId = msg.key
217+
204218 return [
205219 // insert missing message marker (if can't be found)
206220 api.message.html.missing(last(msg.value.content.branch), msg),
207221 result
@@ -210,11 +224,13 @@
210224
211225 var renderedMessage = api.message.html.render(item, {
212226 compact: compactFilter(item),
213227 includeForks: false, // this is a root message, so forks are already displayed as replies
214- priority: highlightItems.has(item.key) ? 2 : 0
228+ priority: getPriority(item)
215229 })
216230
231+ unreadIds.delete(item.key)
232+
217233 if (!renderedMessage) return h('div')
218234 if (lastBumpType) {
219235 var bumps = lastBumpType === 'vote'
220236 ? getLikeAuthors(groupedBumps[lastBumpType])
@@ -228,9 +244,9 @@
228244
229245 // if there are new messages, view full thread goes to the top of those, otherwise to very first reply
230246 var anchorReply = highlightedReplies.length >= 3 ? highlightedReplies[0] : replies[0]
231247
232- return h('FeedEvent -post', {
248+ var result = h('FeedEvent -post', {
233249 attributes: {
234250 'data-root-id': item.key
235251 }
236252 }, [
@@ -240,12 +256,22 @@
240256 h('a.full', {href: item.key, anchor: anchorReply && anchorReply.key}, [i18n('View full thread') + ' (', replies.length, ')'])
241257 ),
242258 h('div.replies', replyElements)
243259 ])
260+
261+ result.msgIds = [item.key].concat(item.replies.map(x => x.key))
262+
263+ return result
244264 }
245265
246- function isHighlighted (msg) {
247- return highlightItems.has(msg.key)
266+ function getPriority (msg) {
267+ if (highlightItems.has(msg.key)) {
268+ return 2
269+ } else if (unreadIds.has(msg.key)) {
270+ return 1
271+ } else {
272+ return 0
273+ }
248274 }
249275 })
250276
251277 function LookupRoot () {
plugs/message/html/layout/default.jsView
@@ -53,8 +53,12 @@
5353 if (priority === 2) {
5454 classList.push('-new')
5555 }
5656
57+ if (priority === 1) {
58+ classList.push('-unread')
59+ }
60+
5761 return h('div', {
5862 classList
5963 }, [
6064 messageHeader(msg, { replyInfo, priority, needsExpand, expanded }),
@@ -85,10 +89,12 @@
8589 // scoped
8690
8791 function messageHeader (msg, {replyInfo, priority}) {
8892 var additionalMeta = []
89- if (priority >= 2) {
93+ if (priority === 2) {
9094 additionalMeta.push(h('span.flag -new', {title: i18n('New Message')}))
95+ } else if (priority === 1) {
96+ additionalMeta.push(h('span.flag -unread', {title: i18n('Unread Message')}))
9197 }
9298 return h('header', [
9399 h('div.main', [
94100 h('a.avatar', {href: `${msg.value.author}`}, [
styles/dark/feed-event.mcssView
@@ -9,9 +9,9 @@
99 :empty {
1010 margin-bottom: -25px
1111 }
1212
13- -new {
13+ -new, -unread {
1414 box-shadow: 0px 0px 2px #ffc800;
1515 background: #fffdf7;
1616 }
1717
styles/dark/message.mcssView
@@ -92,9 +92,9 @@
9292 }
9393 }
9494 }
9595
96- -new {
96+ -new, -unread {
9797 box-shadow: 0 0 1px #efef00;
9898 z-index: 1;
9999 }
100100
@@ -158,25 +158,32 @@
158158 background-position: center
159159 display: inline-block
160160 vertical-align: middle;
161161
162+ -unread {
163+ :after {
164+ content: ' unread'
165+ color: #757474
166+ }
167+ }
168+
162169 -new {
170+ :after {
171+ content: ' new'
172+ color: #757474
173+ }
174+ }
175+
176+ -new, -unread {
163177 width: auto
164178 height: auto
165179 color: #757474
180+ font-size: 75%
166181
167182 :before {
168- content: '✸ new'
169- font-size: 75%
170- }
171-
172- :hover {
173183 color: #efef00
184+ content: '✸'
174185 }
175-
176- :first-letter {
177- color: #efef00
178- }
179186 }
180187 }
181188
182189 em {
styles/light/feed-event.mcssView
@@ -10,9 +10,9 @@
1010 :empty {
1111 margin-bottom: -25px
1212 }
1313
14- -new {
14+ -new, -unread {
1515 box-shadow: 0px 0px 2px #ffc800;
1616 background: #fffdf7;
1717 }
1818
styles/light/message.mcssView
@@ -92,9 +92,9 @@
9292 color: #777
9393 }
9494 }
9595
96- -new {
96+ -new, -unread {
9797 box-shadow: 0 0 1px #ffc600;
9898 z-index: 1;
9999 }
100100
@@ -147,16 +147,36 @@
147147 display: inline-block
148148 vertical-align: middle;
149149 margin-top: -3px;
150150
151+ -unread {
152+ :after {
153+ content: ' unread'
154+ font-size: 75%
155+ color: #b7b7b7
156+ }
157+ }
158+
151159 -new {
152- background-image: svg(new)
160+ :after {
161+ content: ' new'
162+ font-size: 75%
163+ color: #b7b7b7
164+ }
153165 }
154166
155- @svg new {
156- width: 12px
157- height: 12px
158- content: "<circle cx='6' stroke='none' fill='#ffcf04' cy='6' r='5' />"
167+ -new, -unread {
168+ width: auto
169+ height: auto
170+
171+ :before {
172+ color: #ffcf04
173+ content: '✸'
174+ }
175+
176+ :first-letter {
177+ font-size: 100%
178+ }
159179 }
160180 }
161181
162182 em {

Built with git-ssb-web