git ssb

2+

mixmix / ticktack



Tree: 164ee525d1634ae8922a2161019b8894c9a862f7

Files: 164ee525d1634ae8922a2161019b8894c9a862f7 / app / html / thread-card.js

3058 bytesRaw
1var h = require('mutant/h')
2var lodash = require('lodash')
3var nest = require('depnest')
4
5exports.gives = nest('app.html.threadCard', true)
6
7exports.needs = nest({
8 'keys.sync.id': 'first',
9 'history.sync.push': 'first',
10 'about.obs.name': 'first',
11 'about.html.image': 'first',
12 'message.html.markdown': 'first',
13 'translations.sync.strings': 'first'
14})
15
16function isString (s) {
17 return 'string' === typeof s
18}
19
20function firstLine (text) {
21 if(text.length < 80 && !~text.indexOf('\n')) return text
22
23 //get the first non-empty line
24 var line = text.trim().split('\n').shift().trim()
25
26 //always break on a space, so that links are preserved.
27 var i = line.indexOf(' ', 80)
28 var sample = line.substring(0, ~i ? i : line.length)
29
30 const ellipsis = (sample.length < line.length) ? '...' : ''
31 return sample + ellipsis
32}
33
34function trimLeadingMentions (str) {
35 return str.replace(/^(\s*\[@[^\)]+\)\s*)*/, '')
36 // deletes any number of pattern " [@...) " from start of line
37}
38
39function hasBrokenLink (str) {
40 return /\[[^\]]*\]\([^\)]*$/.test(str)
41 // matches "[name](start_of_link"
42}
43
44
45exports.create = function (api) {
46
47 //render the icon for a thread.
48 //it would be more depjecty to split this
49 //into two methods, one in a private plugin
50 //one in a channel plugin
51 function threadIcon (msg) {
52 if(msg.value.private) {
53 const myId = api.keys.sync.id()
54
55 return msg.value.content.recps
56 .map(link => isString(link) ? link : link.link)
57 .filter(link => link !== myId)
58 .map(api.about.html.image)
59 }
60 else if(msg.value.content.channel)
61 return '#'+msg.value.content.channel
62 }
63
64
65 // REFACTOR: move this to a template?
66 function buildRecipientNames (thread) {
67 const myId = api.keys.sync.id()
68
69 return thread.value.content.recps
70 .map(link => isString(link) ? link : link.link)
71 .filter(link => link !== myId)
72 .map(api.about.obs.name)
73 }
74
75 function link(location) {
76 return {'ev-click': () => api.history.sync.push(location)}
77 }
78
79 function subject (msg) {
80 const { subject, text } = msg.value.content
81 if(!(subject || text)) return
82 return api.message.html.markdown(firstLine(subject|| text))
83 }
84
85 return {app: {html: {threadCard: function (thread, opts = {}) {
86 var strings = api.translations.sync.strings()
87
88 if(!thread.value) return
89 if(!thread.value.content.text) return
90
91 const subjectEl = h('div.subject', [
92 opts.nameRecipients
93 ? h('div.recps', buildRecipientNames(thread).map(recp => h('div.recp', recp)))
94 : null,
95 subject(thread)
96 ])
97
98 const lastReply = thread.replies &&
99 lodash.maxBy(thread.replies, function (e) { return e.timestamp })
100
101 var replySample = lastReply ? subject(lastReply) : null
102
103 return h('div.thread', link(thread), [
104 h('div.context', threadIcon(thread)),
105 h('div.content', [
106 subjectEl,
107 replySample ? h('div.reply', [
108 h('div.replySymbol', strings.replySymbol),
109 replySample
110 ]) : null
111 ])
112 ])
113 }}}}
114}
115
116
117

Built with git-ssb-web