Commit fea2881ae175c88bac926fcff65d32598742e9a1
wip mutant thrashing reduction
mix irving committed on 5/2/2018, 5:38:38 AMParent: 858e6680e313a0e7ea426317a18f59ff5c7098c8
Files changed
app/html/comments.js | changed |
app/html/comments.mcss | changed |
app/page/notifications.js | changed |
message/html/comment.js | added |
message/html/comment.mcss | added |
message/index.js | changed |
package.json | changed |
ssb-server-blog-stats.js | changed |
app/html/comments.js | ||
---|---|---|
@@ -1,21 +1,13 @@ | ||
1 | 1 | const nest = require('depnest') |
2 | -const { h, Value, map, computed, when, resolve, throttle } = require('mutant') | |
2 | +const { h, map, Struct, computed, throttle } = require('mutant') | |
3 | 3 | const get = require('lodash/get') |
4 | 4 | |
5 | 5 | exports.gives = nest('app.html.comments') |
6 | 6 | |
7 | 7 | exports.needs = nest({ |
8 | - 'about.html.avatar': 'first', | |
9 | - 'about.obs.name': 'first', | |
10 | - 'backlinks.obs.for': 'first', | |
11 | - 'feed.obs.thread': 'first', | |
8 | + 'message.html.comment': 'first', | |
12 | 9 | 'message.html.compose': 'first', |
13 | - 'message.html.markdown': 'first', | |
14 | - 'message.html.timeago': 'first', | |
15 | - 'message.html.likes': 'first', | |
16 | - 'unread.sync.markRead': 'first', | |
17 | - 'unread.sync.isUnread': 'first', | |
18 | 10 | 'translations.sync.strings': 'first' |
19 | 11 | }) |
20 | 12 | |
21 | 13 | exports.create = (api) => { |
@@ -27,13 +19,18 @@ | ||
27 | 19 | |
28 | 20 | // TODO - move this up into Patchcore |
29 | 21 | const messagesTree = computed(throttle(messages, 200), msgs => { |
30 | 22 | return msgs |
31 | - .filter(msg => forkOf(msg) === undefined) | |
32 | - .map(threadMsg => { | |
33 | - const nestedReplies = msgs.filter(msg => forkOf(msg) === threadMsg.key) | |
34 | - threadMsg.replies = nestedReplies | |
35 | - return threadMsg | |
23 | + .filter(msg => forkOf(msg) === undefined) // exclude nested replies / forks | |
24 | + .filter(msg => msg.value.content.root) // exclude root message / blog | |
25 | + .map(comment => { | |
26 | + const nestedReplies = msgs.filter(msg => forkOf(msg) === comment.key) | |
27 | + | |
28 | + return Struct({ | |
29 | + comment: comment, | |
30 | + replies: nestedReplies | |
31 | + }) | |
32 | + // return Object.assign({}, comment, { replies: nestedReplies }) | |
36 | 33 | }) |
37 | 34 | }) |
38 | 35 | |
39 | 36 | const root = computed(messages, ary => ary[0].key) |
@@ -54,95 +51,22 @@ | ||
54 | 51 | }) |
55 | 52 | |
56 | 53 | return h('Comments', [ |
57 | 54 | // when(twoComposers, compose({ meta, shrink: true, canAttach: false })), |
58 | - map(messagesTree, msg => Comment(msg, root, branch)), | |
55 | + map( | |
56 | + messagesTree, | |
57 | + msg => api.message.html.comment({ comment: msg.comment, replies: msg.replies, branch }), | |
58 | + { | |
59 | + comparer: (a, b) => { | |
60 | + if (a === undefined || b === undefined) return false | |
61 | + | |
62 | + return a.comment() === b.comment() && a.replies().length === b.replies().length | |
63 | + } | |
64 | + } | |
65 | + ), | |
59 | 66 | compose({ meta, feedIdsInThread, shrink: false, canAttach: true, placeholder: strings.writeComment }) |
60 | 67 | ]) |
61 | 68 | } |
62 | - | |
63 | - function Comment (msgObs, root, branch) { | |
64 | - const strings = api.translations.sync.strings() | |
65 | - const msg = resolve(msgObs) | |
66 | - | |
67 | - const raw = get(msg, 'value.content.text') | |
68 | - var className = api.unread.sync.isUnread(msg) ? ' -unread' : ' -read' | |
69 | - api.unread.sync.markRead(msg) | |
70 | - | |
71 | - if (!get(msg, 'value.content.root')) return | |
72 | - | |
73 | - const { author, content } = msg.value | |
74 | - | |
75 | - // // TODO - move this upstream into patchcore:feed.obs.thread ?? | |
76 | - // // OR change strategy to use forks | |
77 | - // const backlinks = api.backlinks.obs.for(msg.key) | |
78 | - // const nestedReplies = computed(backlinks, backlinks => { | |
79 | - // return backlinks.filter(backlinker => { | |
80 | - // const { type, root } = backlinker.value.content | |
81 | - // return type === 'post' && root === msg.key | |
82 | - // }) | |
83 | - // }) | |
84 | - | |
85 | - var nestedReplyCompose = Value(false) | |
86 | - const toggleCompose = () => nestedReplyCompose.set(!nestedReplyCompose()) | |
87 | - const nestedReplyComposer = api.message.html.compose({ | |
88 | - meta: { | |
89 | - type: 'post', | |
90 | - root, | |
91 | - fork: msg.key, | |
92 | - branch, | |
93 | - channel: content.channel | |
94 | - }, | |
95 | - shrink: false, | |
96 | - canAttach: true, | |
97 | - canPreview: false, | |
98 | - placeholder: strings.writeComment | |
99 | - }, toggleCompose) | |
100 | - | |
101 | - return h('Comment', { className }, [ | |
102 | - h('div.left', api.about.html.avatar(author, 'tiny')), | |
103 | - h('div.right', [ | |
104 | - h('section.context', [ | |
105 | - h('div.name', api.about.obs.name(author)), | |
106 | - api.message.html.timeago(msg) | |
107 | - ]), | |
108 | - h('section.content', api.message.html.markdown(raw)), | |
109 | - when(msgObs.replies, | |
110 | - h('section.replies', | |
111 | - map(msgObs.replies, NestedComment) | |
112 | - ) | |
113 | - ), | |
114 | - h('section.actions', [ | |
115 | - h('div.reply', { 'ev-click': toggleCompose }, [ | |
116 | - h('i.fa.fa-commenting-o') | |
117 | - ]), | |
118 | - api.message.html.likes(msg) | |
119 | - ]), | |
120 | - when(nestedReplyCompose, nestedReplyComposer) | |
121 | - ]) | |
122 | - ]) | |
123 | - } | |
124 | - | |
125 | - function NestedComment (msgObs) { | |
126 | - const msg = resolve(msgObs) | |
127 | - const raw = get(msg, 'value.content.text') | |
128 | - if (!raw) return | |
129 | - | |
130 | - const { author } = msg.value | |
131 | - | |
132 | - return h('Comment -nested', [ | |
133 | - h('div.left'), | |
134 | - h('div.right', [ | |
135 | - h('section.context', [ | |
136 | - h('div.name', api.about.obs.name(author)), | |
137 | - api.message.html.timeago(msg) | |
138 | - ]), | |
139 | - h('section.content', api.message.html.markdown(raw)) | |
140 | - ]) | |
141 | - ]) | |
142 | - | |
143 | - api.message.html.markdown(raw) | |
144 | - } | |
145 | 69 | } |
146 | 70 | |
147 | 71 | function forkOf (msg) { |
148 | 72 | return get(msg, 'value.content.fork') |
app/html/comments.mcss | ||
---|---|---|
@@ -7,79 +7,4 @@ | ||
7 | 7 | margin-bottom: 1.5rem |
8 | 8 | } |
9 | 9 | } |
10 | 10 | |
11 | -Comment { | |
12 | - display: flex | |
13 | - | |
14 | - div.left { | |
15 | - margin-right: 1rem | |
16 | - | |
17 | - div.Avatar {} | |
18 | - } | |
19 | - | |
20 | - div.right { | |
21 | - flex-grow: 1 | |
22 | - | |
23 | - $borderBottomLight | |
24 | - padding-bottom: 1rem | |
25 | - margin-bottom: 1rem | |
26 | - | |
27 | - section.context { | |
28 | - display: flex | |
29 | - align-items: baseline | |
30 | - | |
31 | - div.name { | |
32 | - font-size: 1.2rem | |
33 | - margin-right: 1rem | |
34 | - } | |
35 | - div.Timeago {} | |
36 | - } | |
37 | - | |
38 | - section.content { | |
39 | - font-size: .95rem | |
40 | - line-height: 1.4 | |
41 | - div.Markdown {} | |
42 | - } | |
43 | - | |
44 | - section.actions { | |
45 | - font-size: 1rem | |
46 | - color: #555 | |
47 | - margin-right: .5rem | |
48 | - | |
49 | - display: flex | |
50 | - justify-content: flex-end | |
51 | - align-items: baseline | |
52 | - | |
53 | - div.reply { | |
54 | - cursor: pointer | |
55 | - | |
56 | - margin-right: 1.5rem | |
57 | - i.fa {} | |
58 | - } | |
59 | - | |
60 | - div.Likes { } | |
61 | - } | |
62 | - | |
63 | - div.Compose { | |
64 | - margin: 1rem 0 | |
65 | - } | |
66 | - } | |
67 | -} | |
68 | - | |
69 | -Comment -nested { | |
70 | - padding: 1rem 1rem 0 1rem | |
71 | - $backgroundPrimaryText | |
72 | - $roundTop | |
73 | - $roundBottom | |
74 | - | |
75 | - margin-bottom: 1rem | |
76 | - | |
77 | - div.left { margin: 0 } | |
78 | - div.right { | |
79 | - padding: 0 | |
80 | - border: 0 | |
81 | - margin: 0 | |
82 | - | |
83 | - } | |
84 | -} | |
85 | - |
app/page/notifications.js | ||
---|---|---|
@@ -1,6 +1,6 @@ | ||
1 | 1 | const nest = require('depnest') |
2 | -const { h, onceTrue, throttle, Value, Array: MutantArray, map, resolve } = require('mutant') | |
2 | +const { h, onceTrue, throttle, Value, Array: MutantArray, map } = require('mutant') | |
3 | 3 | const pull = require('pull-stream') |
4 | 4 | |
5 | 5 | exports.gives = nest('app.page.notifications') |
6 | 6 | |
@@ -8,16 +8,17 @@ | ||
8 | 8 | // 'app.html.blogCard': 'first', |
9 | 9 | // 'app.html.topNav': 'first', |
10 | 10 | // 'app.html.scroller': 'first', |
11 | 11 | 'app.html.sideNav': 'first', |
12 | + 'message.html.comment': 'first', | |
12 | 13 | // 'blog.sync.isBlog': 'first', |
13 | 14 | // 'feed.pull.public': 'first', |
14 | 15 | // 'feed.pull.type': 'first', |
15 | 16 | // 'history.sync.push': 'first', |
16 | 17 | // 'keys.sync.id': 'first', |
17 | 18 | // 'message.sync.isBlocked': 'first', |
18 | 19 | 'sbot.obs.connection': 'first', |
19 | - 'translations.sync.strings': 'first' | |
20 | + 'translations.sync.strings': 'first', | |
20 | 21 | // 'unread.sync.isUnread': 'first' |
21 | 22 | }) |
22 | 23 | |
23 | 24 | exports.create = (api) => { |
@@ -30,9 +31,8 @@ | ||
30 | 31 | |
31 | 32 | var commentsStore = MutantArray([]) |
32 | 33 | |
33 | 34 | onceTrue(api.sbot.obs.connection, server => { |
34 | - console.log('methods', server.blogStats) | |
35 | 35 | pull( |
36 | 36 | server.blogStats.readAllComments(), |
37 | 37 | pull.drain(m => { |
38 | 38 | commentsStore.push(m) |
@@ -88,14 +88,20 @@ | ||
88 | 88 | // }) |
89 | 89 | |
90 | 90 | return h('Page -notifications', [ |
91 | 91 | api.app.html.sideNav(location), |
92 | - h('div.content', map(throttle(commentsStore, 300), comment => { | |
93 | - const text = comment.value.content.text | |
92 | + h('div.content', map( | |
93 | + throttle(commentsStore, 300), | |
94 | + msg => Comment(msg), | |
95 | + { | |
96 | + // comparer: (a, b) => a === b | |
97 | + } | |
98 | + )) | |
99 | + ]) | |
94 | 100 | |
95 | - return h('p', { style: { margin: '1rem' } }, text) | |
96 | - })) | |
97 | - ]) | |
101 | + function Comment (msg) { | |
102 | + return api.message.html.comment(msg) | |
103 | + } | |
98 | 104 | }) |
99 | 105 | |
100 | 106 | /* function update (soFar, newBlog) { */ |
101 | 107 | // soFar.transaction(() => { |
message/html/comment.js | ||
---|---|---|
@@ -1,0 +1,113 @@ | ||
1 | +const nest = require('depnest') | |
2 | +const { h, Value, map, when, resolve } = require('mutant') | |
3 | +const get = require('lodash/get') | |
4 | + | |
5 | +exports.gives = nest('message.html.comment') | |
6 | + | |
7 | +exports.needs = nest({ | |
8 | + 'about.html.avatar': 'first', | |
9 | + 'about.obs.name': 'first', | |
10 | + // 'backlinks.obs.for': 'first', | |
11 | + 'message.html.compose': 'first', | |
12 | + 'message.html.markdown': 'first', | |
13 | + 'message.html.timeago': 'first', | |
14 | + 'message.html.likes': 'first', | |
15 | + 'unread.sync.markRead': 'first', | |
16 | + 'unread.sync.isUnread': 'first', | |
17 | + 'translations.sync.strings': 'first' | |
18 | +}) | |
19 | + | |
20 | +exports.create = (api) => { | |
21 | + return nest('message.html.comment', Comment) | |
22 | + | |
23 | + function Comment ({ comment: msgObs, replies, branch }) { | |
24 | + const strings = api.translations.sync.strings() | |
25 | + const msg = resolve(msgObs) | |
26 | + | |
27 | + const raw = get(msg, 'value.content.text') | |
28 | + var className = api.unread.sync.isUnread(msg) ? ' -unread' : ' -read' | |
29 | + api.unread.sync.markRead(msg) | |
30 | + | |
31 | + var root = get(msg, 'value.content.root') | |
32 | + if (!root) return | |
33 | + | |
34 | + const { author, content } = msg.value | |
35 | + | |
36 | + // // TODO - move this upstream into patchcore:feed.obs.thread ?? | |
37 | + // // OR change strategy to use forks | |
38 | + // const backlinks = api.backlinks.obs.for(msg.key) | |
39 | + // const nestedReplies = computed(backlinks, backlinks => { | |
40 | + // return backlinks.filter(backlinker => { | |
41 | + // const { type, root } = backlinker.value.content | |
42 | + // return type === 'post' && root === msg.key | |
43 | + // }) | |
44 | + // }) | |
45 | + | |
46 | + var nestedReplyCompose = Value(false) | |
47 | + const toggleCompose = () => nestedReplyCompose.set(!nestedReplyCompose()) | |
48 | + const nestedReplyComposer = api.message.html.compose({ | |
49 | + meta: { | |
50 | + type: 'post', | |
51 | + root, | |
52 | + fork: msg.key, | |
53 | + branch, | |
54 | + channel: content.channel | |
55 | + }, | |
56 | + shrink: false, | |
57 | + canAttach: true, | |
58 | + canPreview: false, | |
59 | + placeholder: strings.writeComment | |
60 | + }, toggleCompose) | |
61 | + | |
62 | + return h('Comment', { className }, [ | |
63 | + h('div.left', api.about.html.avatar(author, 'tiny')), | |
64 | + h('div.right', [ | |
65 | + h('section.context', [ | |
66 | + h('div.name', api.about.obs.name(author)), | |
67 | + api.message.html.timeago(msg) | |
68 | + ]), | |
69 | + h('section.content', api.message.html.markdown(raw)), | |
70 | + when(replies, | |
71 | + h('section.replies', | |
72 | + map( | |
73 | + replies, | |
74 | + NestedComment, | |
75 | + { comparer: (a, b) => a === b } | |
76 | + ) | |
77 | + ) | |
78 | + ), | |
79 | + h('section.actions', [ | |
80 | + h('div.reply', { 'ev-click': toggleCompose }, [ | |
81 | + h('i.fa.fa-commenting-o') | |
82 | + ]), | |
83 | + api.message.html.likes(msg) | |
84 | + ]), | |
85 | + when(nestedReplyCompose, nestedReplyComposer) | |
86 | + ]) | |
87 | + ]) | |
88 | + } | |
89 | + | |
90 | + function NestedComment (msgObs) { | |
91 | + const msg = resolve(msgObs) | |
92 | + const raw = get(msg, 'value.content.text') | |
93 | + if (!raw) return | |
94 | + | |
95 | + const { author } = msg.value | |
96 | + | |
97 | + return h('Comment -nested', [ | |
98 | + h('div.left'), | |
99 | + h('div.right', [ | |
100 | + h('section.context', [ | |
101 | + h('div.name', api.about.obs.name(author)), | |
102 | + api.message.html.timeago(msg) | |
103 | + ]), | |
104 | + h('section.content', api.message.html.markdown(raw)) | |
105 | + ]) | |
106 | + ]) | |
107 | + } | |
108 | +} | |
109 | + | |
110 | +function forkOf (msg) { | |
111 | + return get(msg, 'value.content.fork') | |
112 | +} | |
113 | + |
message/html/comment.mcss | ||
---|---|---|
@@ -1,0 +1,76 @@ | ||
1 | +Comment { | |
2 | + display: flex | |
3 | + | |
4 | + div.left { | |
5 | + margin-right: 1rem | |
6 | + | |
7 | + div.Avatar {} | |
8 | + } | |
9 | + | |
10 | + div.right { | |
11 | + flex-grow: 1 | |
12 | + | |
13 | + $borderBottomLight | |
14 | + padding-bottom: 1rem | |
15 | + margin-bottom: 1rem | |
16 | + | |
17 | + section.context { | |
18 | + display: flex | |
19 | + align-items: baseline | |
20 | + | |
21 | + div.name { | |
22 | + font-size: 1.2rem | |
23 | + margin-right: 1rem | |
24 | + } | |
25 | + div.Timeago {} | |
26 | + } | |
27 | + | |
28 | + section.content { | |
29 | + font-size: .95rem | |
30 | + line-height: 1.4 | |
31 | + div.Markdown {} | |
32 | + } | |
33 | + | |
34 | + section.actions { | |
35 | + font-size: 1rem | |
36 | + color: #555 | |
37 | + margin-right: .5rem | |
38 | + | |
39 | + display: flex | |
40 | + justify-content: flex-end | |
41 | + align-items: baseline | |
42 | + | |
43 | + div.reply { | |
44 | + cursor: pointer | |
45 | + | |
46 | + margin-right: 1.5rem | |
47 | + i.fa {} | |
48 | + } | |
49 | + | |
50 | + div.Likes { } | |
51 | + } | |
52 | + | |
53 | + div.Compose { | |
54 | + margin: 1rem 0 | |
55 | + } | |
56 | + } | |
57 | +} | |
58 | + | |
59 | +Comment -nested { | |
60 | + padding: 1rem 1rem 0 1rem | |
61 | + $backgroundPrimaryText | |
62 | + $roundTop | |
63 | + $roundBottom | |
64 | + | |
65 | + margin-bottom: 1rem | |
66 | + | |
67 | + div.left { margin: 0 } | |
68 | + div.right { | |
69 | + padding: 0 | |
70 | + border: 0 | |
71 | + margin: 0 | |
72 | + | |
73 | + } | |
74 | +} | |
75 | + | |
76 | + |
message/index.js | ||
---|---|---|
@@ -3,8 +3,9 @@ | ||
3 | 3 | publish: require('./async/publish') |
4 | 4 | }, |
5 | 5 | html: { |
6 | 6 | channel: require('./html/channel'), |
7 | + comment: require('./html/comment'), | |
7 | 8 | compose: require('./html/compose'), |
8 | 9 | likes: require('./html/likes'), |
9 | 10 | subject: require('./html/subject'), |
10 | 11 | timeago: require('./html/timeago') |
package.json | ||
---|---|---|
@@ -40,9 +40,9 @@ | ||
40 | 40 | "medium-editor": "^5.23.3", |
41 | 41 | "medium-editor-markdown": "^2.6.0", |
42 | 42 | "micro-css": "^2.0.1", |
43 | 43 | "morphdom": "^2.3.3", |
44 | - "mutant": "^3.21.2", | |
44 | + "mutant": "^3.22.1", | |
45 | 45 | "mutant-scroll": "0.0.5", |
46 | 46 | "open-external": "^0.1.1", |
47 | 47 | "patch-drafts": "0.0.6", |
48 | 48 | "patch-history": "^1.0.0", |
ssb-server-blog-stats.js | ||
---|---|---|
@@ -25,9 +25,9 @@ | ||
25 | 25 | readAllComments: 'source', // TEMP |
26 | 26 | readLikes: 'source' |
27 | 27 | }, |
28 | 28 | init: (server, config) => { |
29 | - console.log('initialising blog-stats plugin') | |
29 | + console.log('> initialising blog-stats plugin') | |
30 | 30 | const myKey = server.keys.id |
31 | 31 | |
32 | 32 | const view = server._flumeUse( |
33 | 33 | 'internalblogStats', |
@@ -136,10 +136,10 @@ | ||
136 | 136 | |
137 | 137 | const _source = pull( |
138 | 138 | view.read({ |
139 | 139 | // live: true, |
140 | - gt: [ 'B~', undefined, undefined ], | |
141 | - lt: [ 'C~', null, null ], | |
140 | + gt: [ 'C', null, null ], | |
141 | + lt: [ 'C', undefined, undefined ], | |
142 | 142 | reverse: true, |
143 | 143 | values: true, |
144 | 144 | keys: true, |
145 | 145 | seqs: false |
@@ -149,14 +149,9 @@ | ||
149 | 149 | }), |
150 | 150 | pull.map(result => result.value) |
151 | 151 | ) |
152 | 152 | |
153 | - // pull( | |
154 | - // _source, | |
155 | - // pull.log() | |
156 | - // ) | |
157 | 153 | source.resolve(_source) |
158 | - // source.resolve(pull.values([1, 2, 3, 4, ':)'])) | |
159 | 154 | }) |
160 | 155 | |
161 | 156 | return pull( |
162 | 157 | source |
Built with git-ssb-web