git ssb

10+

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