Commit c948308a09c8225c1c36b7910e2f7c3e8522127e
rework like / quote / reply + message layout, install scuttle-thread
mixmix committed on 11/23/2018, 11:15:33 AMParent: dd6a279d35c61c3c1a36d453b6e27af326a3fc67
Files changed
app/html/scroller.mcss | changed |
app/page/notifications.js | changed |
app/page/private.js | changed |
app/page/public.js | changed |
app/page/thread.js | changed |
app/sync/goTo.js | changed |
message/html/layout/default.js | changed |
message/html/layout/default.mcss | changed |
message/html/like.js | changed |
message/html/meta/raw.js | changed |
message/html/action/likes.js | deleted |
message/html/action/quote.js | deleted |
message/html/action/reply.js | deleted |
message/html/like.mcss | added |
message/html/quote.js | added |
message/html/quote.mcss | added |
message/html/reply.js | added |
message/html/reply.mcss | added |
package-lock.json | changed |
package.json | changed |
app/html/scroller.mcss | ||
---|---|---|
@@ -9,9 +9,9 @@ | ||
9 | 9 … | |
10 | 10 … | display: grid |
11 | 11 … | justify-content: stretch |
12 | 12 … | align-content: start |
13 | - grid-template-columns: auto minmax(740px, 900px) auto | |
13 … | + grid-template-columns: auto minmax(740px, 1100px) auto | |
14 | 14 … | |
15 | 15 … | section { |
16 | 16 … | grid-column: 2 / 3 |
17 | 17 … |
app/page/notifications.js | ||
---|---|---|
@@ -41,23 +41,27 @@ | ||
41 | 41 … | |
42 | 42 … | pull( |
43 | 43 … | pullMentions({ old: false, live: true }), |
44 | 44 … | filterDownThrough(), |
45 | - Scroller(container, content, api.message.html.render, true, false) | |
45 … | + Scroller(container, content, render, true, false) | |
46 | 46 … | ) |
47 | 47 … | |
48 | 48 … | pull( |
49 | 49 … | pullMentions({ reverse: true, live: false }), |
50 | 50 … | filterUpThrough(), |
51 | - Scroller(container, content, api.message.html.render, false, false) | |
51 … | + Scroller(container, content, render, false, false) | |
52 | 52 … | ) |
53 | 53 … | } |
54 | 54 … | draw() |
55 | 55 … | |
56 | 56 … | container.title = '/notifications' |
57 | 57 … | return container |
58 | 58 … | } |
59 | 59 … | |
60 … | + function render (msg) { | |
61 … | + return api.message.html.render(msg, { showTitle: true }) | |
62 … | + } | |
63 … | + | |
60 | 64 … | // NOTE - currently this stream is know to pick up: |
61 | 65 … | // - post mentions (public) |
62 | 66 … | // - patchwork replies (public) |
63 | 67 … | // - scry (public, private) |
app/page/private.js | ||
---|---|---|
@@ -57,23 +57,27 @@ | ||
57 | 57 … | |
58 | 58 … | pull( |
59 | 59 … | pullPrivate({ old: false, live: true }), |
60 | 60 … | filterDownThrough(), |
61 | - Scroller(container, content, api.message.html.render, true, false) | |
61 … | + Scroller(container, content, render, true, false) | |
62 | 62 … | ) |
63 | 63 … | |
64 | 64 … | pull( |
65 | 65 … | pullPrivate({ reverse: true }), |
66 | 66 … | filterUpThrough(), |
67 | - Scroller(container, content, api.message.html.render, false, false) | |
67 … | + Scroller(container, content, render, false, false) | |
68 | 68 … | ) |
69 | 69 … | } |
70 | 70 … | draw() |
71 | 71 … | |
72 | 72 … | container.title = '/private' |
73 | 73 … | return container |
74 | 74 … | } |
75 | 75 … | |
76 … | + function render (msg) { | |
77 … | + return api.message.html.render(msg, { showTitle: true }) | |
78 … | + } | |
79 … | + | |
76 | 80 … | function pullPrivate (opts) { |
77 | 81 … | const query = [{ |
78 | 82 … | $filter: { |
79 | 83 … | timestamp: { $gt: 0 }, |
app/page/public.js | ||
---|---|---|
@@ -44,11 +44,11 @@ | ||
44 | 44 … | const createStream = (opts) => api.sbot.pull.stream(server => { |
45 | 45 … | const _opts = merge({}, opts, { |
46 | 46 … | query: [{ |
47 | 47 … | $filter: { |
48 | - timestamp: {$gt: 0, $lt: undefined}, | |
48 … | + timestamp: { $gt: 0, $lt: undefined }, | |
49 | 49 … | value: { |
50 | - content: { recps: {$not: true} } | |
50 … | + content: { recps: { $not: true } } | |
51 | 51 … | } |
52 | 52 … | } |
53 | 53 … | }], |
54 | 54 … | limit: 100 |
@@ -62,20 +62,20 @@ | ||
62 | 62 … | resetFeed({ container, content }) |
63 | 63 … | |
64 | 64 … | const render = (msg) => { |
65 | 65 … | // if (msg.value.content.type === 'about') debugger |
66 | - return api.message.html.render(msg) | |
66 … | + return api.message.html.render(msg, { showTitle: true }) | |
67 | 67 … | } |
68 | 68 … | |
69 | 69 … | // TODO - change to use ssb-query, streamed by publish time |
70 | 70 … | pull( |
71 | - createStream({old: false, live: true}), | |
71 … | + createStream({ old: false, live: true }), | |
72 | 72 … | filterUpThrough(), |
73 | 73 … | Scroller(container, content, render, true, false) |
74 | 74 … | ) |
75 | 75 … | |
76 | 76 … | pull( |
77 | - createStream({reverse: true, live: false}), | |
77 … | + createStream({ reverse: true, live: false }), | |
78 | 78 … | filterDownThrough(), |
79 | 79 … | Scroller(container, content, render, false, false) |
80 | 80 … | ) |
81 | 81 … | } |
app/page/thread.js | ||
---|---|---|
@@ -81,11 +81,11 @@ | ||
81 | 81 … | function locateKey () { |
82 | 82 … | // wait till we're on the right page |
83 | 83 … | if (tabs.currentPage().id !== locationId) return setTimeout(locateKey, 200) |
84 | 84 … | |
85 | - if (!tabs.currentPage().scroll) return setTimeout(locateKey, 200) | |
85 … | + if (!tabs.currentPage().keyboardScroll) return setTimeout(locateKey, 200) | |
86 | 86 … | |
87 | - tabs.currentPage().scroll('first') | |
87 … | + tabs.currentPage().keyboardScroll('first') | |
88 | 88 … | const msg = tabs.currentPage().querySelector(`[data-id='${id}']`) |
89 | 89 … | if (!msg) return setTimeout(locateKey, 200) |
90 | 90 … | |
91 | 91 … | ;(msg.scrollIntoViewIfNeeded || msg.scrollIntoView).call(msg) |
app/sync/goTo.js | ||
---|---|---|
@@ -42,10 +42,10 @@ | ||
42 | 42 … | api.history.sync.push(loc) |
43 | 43 … | |
44 | 44 … | if (loc.action === 'quote' && page.firstChild && page.firstChild.addQuote) { |
45 | 45 … | page.firstChild.addQuote(loc.value) |
46 | - tabs.currentPage().scroll('last') | |
47 | - } else if (loc.action === 'reply') { tabs.currentPage().scroll('last') } | |
46 … | + tabs.currentPage().keyboardScroll('last') | |
47 … | + } else if (loc.action === 'reply') { tabs.currentPage().keyboardScroll('last') } | |
48 | 48 … | |
49 | 49 … | return true |
50 | 50 … | } |
51 | 51 … |
message/html/layout/default.js | ||
---|---|---|
@@ -1,15 +1,17 @@ | ||
1 | 1 … | const nest = require('depnest') |
2 | 2 … | const { h, Value } = require('mutant') |
3 | -const { isMsg } = require('ssb-ref') | |
3 … | +// const { isMsg } = require('ssb-ref') | |
4 | 4 … | |
5 | 5 … | exports.needs = nest({ |
6 | 6 … | 'about.html.avatar': 'first', |
7 | 7 … | 'keys.sync.id': 'first', |
8 | - 'message.html.action': 'map', | |
9 | 8 … | 'message.html.author': 'first', |
10 | 9 … | 'message.html.backlinks': 'first', |
10 … | + 'message.html.like': 'first', | |
11 | 11 … | 'message.html.meta': 'map', |
12 … | + 'message.html.quote': 'first', | |
13 … | + 'message.html.reply': 'first', | |
12 | 14 … | 'message.html.timestamp': 'first', |
13 | 15 … | 'sbot.async.run': 'first' |
14 | 16 … | }) |
15 | 17 … | |
@@ -18,32 +20,40 @@ | ||
18 | 20 … | exports.create = (api) => { |
19 | 21 … | return nest('message.html.layout', messageLayout) |
20 | 22 … | |
21 | 23 … | function messageLayout (msg, opts = {}) { |
22 | - const { layout, showUnread = true } = opts | |
23 | - if (!(layout === undefined || layout === 'default')) return | |
24 … | + if (!(opts.layout === undefined || opts.layout === 'default')) return | |
25 … | + const { showUnread = true, showTitle } = opts | |
24 | 26 … | |
25 | - var { author, timestamp, meta, action, backlinks } = api.message.html | |
26 | - if (!isMsg(msg.key)) action = () => {} | |
27 … | + var { author, timestamp, like, meta, backlinks, quote, reply } = api.message.html | |
27 | 28 … | |
28 | 29 … | var rawMessage = Value(null) |
29 | 30 … | |
30 | 31 … | var el = h('Message -default', |
31 | 32 … | { attributes: { tabindex: '0' } }, // needed to be able to navigate and show focus() |
32 | 33 … | [ |
33 | - h('section.avatar', {}, api.about.html.avatar(msg.value.author)), | |
34 | - h('section.top', [ | |
34 … | + h('section.left', [ | |
35 … | + h('div.avatar', {}, api.about.html.avatar(msg.value.author)), | |
35 | 36 … | h('div.author', {}, author(msg)), |
36 | - h('div.title', {}, opts.title), | |
37 | - h('div.meta', {}, meta(msg, { rawMessage })) | |
37 … | + h('div.timestamp', {}, timestamp(msg)) | |
38 | 38 … | ]), |
39 | - h('section.content', {}, opts.content), | |
40 | - h('section.raw-content', rawMessage), | |
41 | - h('section.bottom', [ | |
42 | - h('div.timestamp', {}, timestamp(msg)), | |
43 | - h('div.actions', {}, action(msg)) | |
39 … | + | |
40 … | + h('section.body', [ | |
41 … | + showTitle ? h('div.title', {}, opts.title) : null, | |
42 … | + h('div.content', {}, opts.content), | |
43 … | + h('footer.backlinks', {}, backlinks(msg)), | |
44 … | + h('div.raw-content', rawMessage) | |
44 | 45 … | ]), |
45 | - h('footer.backlinks', {}, backlinks(msg)) | |
46 … | + | |
47 … | + h('section.right', [ | |
48 … | + h('div.meta', {}, meta(msg, { rawMessage })), | |
49 … | + // isMsg(msg.key) ? // don't show actions if no msg.key | |
50 … | + h('div.actions', [ | |
51 … | + like(msg), | |
52 … | + quote(msg), | |
53 … | + reply(msg) | |
54 … | + ]) | |
55 … | + ]) | |
46 | 56 … | ] |
47 | 57 … | ) |
48 | 58 … | |
49 | 59 … | // UnreadFeature (search codebase for this if extracting) |
message/html/layout/default.mcss | ||
---|---|---|
@@ -1,132 +1,132 @@ | ||
1 | 1 … | Message -default { |
2 | 2 … | padding: 1rem .5rem |
3 | 3 … | |
4 | 4 … | display: grid |
5 | - grid-template-columns: 5rem auto | |
6 | - grid-row-gap: .5rem | |
5 … | + grid-template-columns: 6rem 1fr auto | |
6 … | + grid-gap: 1.5rem | |
7 | 7 … | |
8 | - section.avatar { | |
9 | - grid-column: 1 / 2 | |
10 | - grid-row: 1 / span 4 | |
11 | - a img { | |
8 … | + section.left { | |
9 … | + grid-column: 1 | |
10 … | + | |
11 … | + display: grid | |
12 … | + align-content: start | |
13 … | + justify-items: end | |
14 … | + | |
15 … | + div.avatar { | |
16 … | + grid-row: 1 | |
17 … | + a img { } | |
12 | 18 … | } |
13 | - } | |
14 | 19 … | |
15 | - section.top { | |
16 | - grid-column: 2 / 3 | |
17 | - grid-row: 1 / span 1 | |
18 | - | |
19 | - display: flex | |
20 | - align-items: baseline | |
21 | - | |
22 | 20 … | div.author { |
21 … | + grid-row: 2 | |
23 | 22 … | font-weight: 600 |
24 | - margin-right: .5rem | |
23 … | + text-align: right | |
25 | 24 … | (a) { color: #222 } |
26 | 25 … | } |
27 | 26 … | |
27 … | + div.timestamp { | |
28 … | + grid-row: 3 | |
29 … | + a { | |
30 … | + font-size: .9rem | |
31 … | + $textSubtle | |
32 … | + } | |
33 … | + } | |
34 … | + } | |
35 … | + | |
36 … | + section.body { | |
37 … | + grid-column: 2 | |
38 … | + | |
39 … | + display: grid | |
40 … | + align-content: start | |
41 … | + | |
28 | 42 … | div.title { |
29 | - flex-grow: 1 | |
43 … | + grid-row: 1 | |
30 | 44 … | font-size: .9rem |
31 | 45 … | $textSubtle |
32 | 46 … | (a) { $textSubtle } |
33 | 47 … | } |
34 | 48 … | |
35 | - div.meta { | |
36 | - display: flex | |
37 | - justify-content: flex-end | |
38 | - align-items: baseline | |
39 | - | |
40 | - i, div, a { | |
41 | - margin-left: .5rem | |
49 … | + div.content { | |
50 … | + grid-row: 2 | |
51 … | + (img) { | |
52 … | + max-width: 100% | |
42 | 53 … | } |
54 … | + (video) { | |
55 … | + max-width: 100% | |
56 … | + } | |
43 | 57 … | } |
44 | - } | |
45 | 58 … | |
46 | - section.content { | |
47 | - grid-column: 2 / 3 | |
48 | - grid-row: 2 / span 1 | |
59 … | + footer.backlinks { | |
60 … | + grid-row: 3 | |
61 … | + } | |
49 | 62 … | |
50 | - (img) { | |
51 | - max-width: 100% | |
63 … | + div.raw-content { | |
64 … | + grid-row: 4 | |
65 … | + pre { | |
66 … | + border: 1px gainsboro solid | |
67 … | + padding: .8rem | |
68 … | + background-color: #f5f5f5 | |
69 … | + color: #c121dc | |
70 … | + padding: .3rem | |
71 … | + white-space: pre-wrap | |
72 … | + word-wrap: break-word | |
73 … | + | |
74 … | + span { | |
75 … | + font-weight: 600 | |
76 … | + } | |
77 … | + a { | |
78 … | + word-break: break-all | |
79 … | + } | |
80 … | + } | |
52 | 81 … | } |
53 | - (video) { | |
54 | - max-width: 100% | |
55 | - } | |
82 … | + | |
56 | 83 … | } |
57 | 84 … | |
58 | - section.bottom { | |
59 | - grid-column: 2 / 3 | |
60 | - grid-row: 4 / span 1 | |
85 … | + section.right { | |
86 … | + grid-column: 3 | |
61 | 87 … | |
62 | - display: flex | |
63 | - align-items: center | |
88 … | + display: grid | |
89 … | + justify-items: end | |
90 … | + align-content: space-between | |
64 | 91 … | |
65 | - div.timestamp { | |
66 | - flex-grow: 1 | |
92 … | + div.meta { | |
93 … | + grid-row: 1 | |
67 | 94 … | |
68 | - a { | |
69 | - font-size: .9rem | |
70 | - $textSubtle | |
71 | - } | |
95 … | + display: grid | |
96 … | + justify-items: end | |
97 … | + grid-gap: .5rem | |
98 … | + | |
99 … | + i, div, a { } | |
100 … | + | |
101 … | + a.channel { grid-row: 1 } | |
72 | 102 … | } |
73 | 103 … | |
74 | 104 … | div.actions { |
105 … | + grid-row: 2 | |
106 … | + justify-self: end | |
107 … | + | |
75 | 108 … | display: grid |
76 | 109 … | grid-auto-flow: column |
110 … | + grid-gap: .8rem | |
77 | 111 … | |
78 | 112 … | font-size: .9rem |
79 | - a { | |
80 | - margin-left: .5em | |
81 | - } | |
82 | 113 … | |
83 | - a.likes { grid-column: 1 } | |
84 | - a.like, a.unlike { grid-column: 2 } | |
85 | - a.unlike { | |
86 | - $textSubtle | |
87 | - } | |
114 … | + div.MessageLike { } | |
115 … | + i.MessageQuote { margin-top: 3px } | |
116 … | + i.MessageReply { margin-top: 1px } | |
88 | 117 … | } |
89 | 118 … | } |
90 | 119 … | |
91 | - section.raw-content { | |
92 | - grid-column: 2 / 3 | |
93 | - grid-row: 3 / span 1 | |
94 | - | |
95 | - pre { | |
96 | - border: 1px gainsboro solid | |
97 | - padding: .8rem | |
98 | - background-color: #f5f5f5 | |
99 | - color: #c121dc | |
100 | - padding: .3rem | |
101 | - white-space: pre-wrap | |
102 | - word-wrap: break-word | |
103 | - | |
104 | - span { | |
105 | - font-weight: 600 | |
106 | - } | |
107 | - a { | |
108 | - word-break: break-all | |
109 | - } | |
110 | - } | |
111 | - } | |
112 | - | |
113 | - footer.backlinks { | |
114 | - grid-row: 5 / span 1 | |
115 | - | |
116 | - grid-column: 2 / 3 | |
117 | - flex-basis: 100% | |
118 | - } | |
119 | - | |
120 | 120 … | /* UnreadFeature (search codebase for this if extracting) */ |
121 | 121 … | |
122 | 122 … | /* initially read */ |
123 | 123 … | -read { |
124 | 124 … | } |
125 | 125 … | |
126 | 126 … | /* initially unread */ |
127 | 127 … | -unread { |
128 | - section.top { | |
128 … | + section.right { | |
129 | 129 … | div.meta { |
130 | 130 … | i.unread { |
131 | 131 … | display: initial |
132 | 132 … | transition: color 1s ease-in |
@@ -138,9 +138,9 @@ | ||
138 | 138 … | |
139 | 139 … | /* initially unread, but subsequently marked read */ |
140 | 140 … | -unread { |
141 | 141 … | -read { |
142 | - section.top { | |
142 … | + section.right { | |
143 | 143 … | div.meta { |
144 | 144 … | i.unread { |
145 | 145 … | color: #bbb |
146 | 146 … | } |
message/html/like.js | ||
---|---|---|
@@ -1,50 +1,44 @@ | ||
1 | -var { h, computed, when } = require('mutant') | |
1 … | +var { h, computed } = require('mutant') | |
2 | 2 … | var nest = require('depnest') |
3 … | +const Scuttle = require('scuttle-thread') | |
3 | 4 … | |
4 | 5 … | exports.needs = nest({ |
5 | 6 … | 'keys.sync.id': 'first', |
6 | 7 … | 'message.obs.likes': 'first', |
7 | - 'sbot.async.publish': 'first' | |
8 … | + 'sbot.obs.connection': 'first' | |
8 | 9 … | }) |
9 | 10 … | |
10 | 11 … | exports.gives = nest('message.html.like') |
11 | 12 … | |
12 | 13 … | exports.create = (api) => { |
13 | - return nest('message.html.like', function like (msg) { | |
14 | - var id = api.keys.sync.id() | |
15 | - var liked = computed([api.message.obs.likes(msg.key), id], doesLike) | |
16 | - return when(liked, | |
17 | - h('a.unlike', { | |
18 | - href: '#', | |
19 | - 'ev-click': () => publishLike(msg, false) | |
20 | - }, 'Unlike'), | |
21 | - h('a.like', { | |
22 | - href: '#', | |
23 | - 'ev-click': () => publishLike(msg, true) | |
24 | - }, 'Like') | |
25 | - ) | |
26 | - }) | |
14 … | + return nest('message.html.like', like) | |
27 | 15 … | |
28 | - function publishLike (msg, status = true) { | |
29 | - var like = status ? { | |
30 | - type: 'vote', | |
31 | - channel: msg.value.content.channel, | |
32 | - vote: { link: msg.key, value: 1, expression: 'Like' } | |
33 | - } : { | |
34 | - type: 'vote', | |
35 | - channel: msg.value.content.channel, | |
36 | - vote: { link: msg.key, value: 0, expression: 'Unlike' } | |
37 | - } | |
38 | - if (msg.value.content.recps) { | |
39 | - like.recps = msg.value.content.recps.map(function (e) { | |
40 | - return e && typeof e !== 'string' ? e.link : e | |
41 | - }) | |
42 | - like.private = true | |
43 | - } | |
44 | - api.sbot.async.publish(like) | |
16 … | + function like (msg) { | |
17 … | + const id = api.keys.sync.id() | |
18 … | + | |
19 … | + // TODO make this full-async : | |
20 … | + // - get whether i like this currently | |
21 … | + // - only update after I click like/ unlike | |
22 … | + | |
23 … | + return computed(api.message.obs.likes(msg.key), likes => { | |
24 … | + const iLike = likes.includes(id) | |
25 … | + | |
26 … | + return h('MessageLike', | |
27 … | + { | |
28 … | + className: iLike ? '-liked' : '', | |
29 … | + 'ev-click': () => publishLike(msg, !iLike) | |
30 … | + }, | |
31 … | + [ | |
32 … | + h('span.count', likes.length ? likes.length : ''), | |
33 … | + h('i.fa', { className: iLike ? 'fa-heart' : 'fa-heart-o' }) | |
34 … | + ] | |
35 … | + ) | |
36 … | + }) | |
45 | 37 … | } |
46 | -} | |
47 | 38 … | |
48 | -function doesLike (likes, userId) { | |
49 | - return likes.includes(userId) | |
39 … | + function publishLike (msg, value = true) { | |
40 … | + const scuttle = Scuttle(api.sbot.obs.connection) | |
41 … | + | |
42 … | + scuttle.like(msg, { value }, console.log) | |
43 … | + } | |
50 | 44 … | } |
message/html/meta/raw.js | ||
---|---|---|
@@ -54,8 +54,8 @@ | ||
54 | 54 … | var refRegex = /((?:@|%|&)[A-Za-z0-9/+]{43}=\.[\w\d]+)/g |
55 | 55 … | |
56 | 56 … | var arr = text.split(refRegex) |
57 | 57 … | for (var i = 1; i < arr.length; i += 2) { |
58 | - arr[i] = h('a', {href: arr[i]}, arr[i]) | |
58 … | + arr[i] = h('a', { href: arr[i] }, arr[i]) | |
59 | 59 … | } |
60 | 60 … | return arr |
61 | 61 … | } |
message/html/action/likes.js | ||
---|---|---|
@@ -1,32 +1,0 @@ | ||
1 | -const nest = require('depnest') | |
2 | -const { h, computed, map } = require('mutant') | |
3 | -const ref = require('ssb-ref') | |
4 | - | |
5 | -exports.gives = nest('message.html.action') | |
6 | - | |
7 | -exports.needs = nest({ | |
8 | - 'about.obs.name': 'first', | |
9 | - 'message.obs.likes': 'first' | |
10 | -}) | |
11 | - | |
12 | -exports.create = (api) => { | |
13 | - return nest('message.html.action', likes) | |
14 | - | |
15 | - function likes (msg) { | |
16 | - if (!ref.isMsgId(msg.key)) return | |
17 | - | |
18 | - const symbol = '\u2713' // tick 🗸 | |
19 | - | |
20 | - var likes = api.message.obs.likes(msg.key) | |
21 | - | |
22 | - var body = computed(likes, likes => likes.length > 4 | |
23 | - ? likes.length + ' ' + symbol | |
24 | - : Array(likes.length).fill(symbol).join('') | |
25 | - ) | |
26 | - | |
27 | - var names = map(likes, id => api.about.obs.name(id)) | |
28 | - var title = computed(names, names => names.map(n => '@' + n).join('\n')) | |
29 | - | |
30 | - return h('a.likes', { title }, body) | |
31 | - } | |
32 | -} |
message/html/action/quote.js | ||
---|---|---|
@@ -1,17 +1,0 @@ | ||
1 | -var h = require('mutant/h') | |
2 | -var nest = require('depnest') | |
3 | - | |
4 | -exports.needs = nest({ | |
5 | - 'app.sync.goTo': 'first' | |
6 | -}) | |
7 | - | |
8 | -exports.gives = nest('message.html.action') | |
9 | - | |
10 | -exports.create = (api) => { | |
11 | - return nest('message.html.action', function quote (msg) { | |
12 | - return h('a', { | |
13 | - href: '#', | |
14 | - 'ev-click': (ev) => { ev.preventDefault(); api.app.sync.goTo({ action: 'quote', key: msg.key, value: msg.value }) } | |
15 | - }, 'Quote') | |
16 | - }) | |
17 | -} |
message/html/action/reply.js | ||
---|---|---|
@@ -1,17 +1,0 @@ | ||
1 | -var h = require('mutant/h') | |
2 | -var nest = require('depnest') | |
3 | - | |
4 | -exports.needs = nest({ | |
5 | - 'app.sync.goTo': 'first' | |
6 | -}) | |
7 | - | |
8 | -exports.gives = nest('message.html.action') | |
9 | - | |
10 | -exports.create = (api) => { | |
11 | - return nest('message.html.action', function betterReply (msg) { | |
12 | - return h('a', { | |
13 | - href: '#', | |
14 | - 'ev-click': (ev) => { ev.preventDefault(); api.app.sync.goTo({ action: 'reply', key: msg.key, value: msg.value }) } | |
15 | - }, 'Reply') | |
16 | - }) | |
17 | -} |
message/html/like.mcss | ||
---|---|---|
@@ -1,0 +1,22 @@ | ||
1 … | +MessageLike { | |
2 … | + color: gray | |
3 … | + cursor: pointer | |
4 … | + | |
5 … | + display: grid | |
6 … | + grid-template-columns: auto auto | |
7 … | + align-items: center | |
8 … | + grid-gap: .2rem | |
9 … | + | |
10 … | + span.count {} | |
11 … | + i.fa {} | |
12 … | + | |
13 … | + -liked { | |
14 … | + i.fa { color: red } | |
15 … | + } | |
16 … | + | |
17 … | + :hover { | |
18 … | + i.fa { | |
19 … | + color: red | |
20 … | + } | |
21 … | + } | |
22 … | +} |
message/html/quote.js | ||
---|---|---|
@@ -1,0 +1,22 @@ | ||
1 … | +var h = require('mutant/h') | |
2 … | +var nest = require('depnest') | |
3 … | + | |
4 … | +exports.gives = nest('message.html.quote') | |
5 … | + | |
6 … | +exports.needs = nest({ | |
7 … | + 'app.sync.goTo': 'first' | |
8 … | +}) | |
9 … | + | |
10 … | +exports.create = (api) => { | |
11 … | + return nest('message.html.quote', function quote (msg) { | |
12 … | + return h('i.MessageQuote.fa.fa-quote-right', | |
13 … | + { | |
14 … | + 'ev-click': (ev) => { | |
15 … | + ev.preventDefault() | |
16 … | + api.app.sync.goTo({ action: 'quote', key: msg.key, value: msg.value }) | |
17 … | + }, | |
18 … | + title: 'quote' | |
19 … | + } | |
20 … | + ) | |
21 … | + }) | |
22 … | +} |
message/html/quote.mcss | ||
---|---|---|
@@ -1,0 +1,6 @@ | ||
1 … | +MessageQuote { | |
2 … | + color: #c9c9c9 | |
3 … | + | |
4 … | + cursor: pointer | |
5 … | + :hover { color: gray } | |
6 … | +} |
message/html/reply.js | ||
---|---|---|
@@ -1,0 +1,22 @@ | ||
1 … | +var h = require('mutant/h') | |
2 … | +var nest = require('depnest') | |
3 … | + | |
4 … | +exports.gives = nest('message.html.reply') | |
5 … | + | |
6 … | +exports.needs = nest({ | |
7 … | + 'app.sync.goTo': 'first' | |
8 … | +}) | |
9 … | + | |
10 … | +exports.create = (api) => { | |
11 … | + return nest('message.html.reply', function betterReply (msg) { | |
12 … | + return h('i.MessageReply.fa.fa-comment', | |
13 … | + { | |
14 … | + title: 'reply', | |
15 … | + 'ev-click': (ev) => { | |
16 … | + ev.preventDefault() | |
17 … | + api.app.sync.goTo({ action: 'reply', key: msg.key, value: msg.value }) | |
18 … | + } | |
19 … | + } | |
20 … | + ) | |
21 … | + }) | |
22 … | +} |
message/html/reply.mcss | ||
---|---|---|
@@ -1,0 +1,6 @@ | ||
1 … | +MessageReply { | |
2 … | + color: #c9c9c9 | |
3 … | + | |
4 … | + cursor: pointer | |
5 … | + :hover { color: gray } | |
6 … | +} |
package-lock.json | ||
---|---|---|
The diff is too large to show. Use a local git client to view these changes. Old file size: 381120 bytes New file size: 382012 bytes |
package.json | ||
---|---|---|
@@ -82,8 +82,9 @@ | ||
82 | 82 … | "pull-stream": "^3.6.9", |
83 | 83 … | "read-directory": "^3.0.1", |
84 | 84 … | "require-style": "^1.0.1", |
85 | 85 … | "scuttle-blog": "^1.0.1", |
86 … | + "scuttle-thread": "^1.0.1", | |
86 | 87 … | "scuttlebot": "^13.0.2", |
87 | 88 … | "setimmediate": "^1.0.5", |
88 | 89 … | "ssb-about": "^2.0.0", |
89 | 90 … | "ssb-backlinks": "^0.7.3", |
Built with git-ssb-web