git ssb

2+

mixmix / ticktack



Tree: 6c2d62189f2bd14a50a90b56b6e4b20393233a56

Files: 6c2d62189f2bd14a50a90b56b6e4b20393233a56 / app / html / thread-card.js

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

Built with git-ssb-web