git ssb

2+

mixmix / ticktack



Tree: 1ff52dc468c28cdb7ae8aacd80a6a310a42e91b3

Files: 1ff52dc468c28cdb7ae8aacd80a6a310a42e91b3 / app / html / blogCard.js

3876 bytesRaw
1var nest = require('depnest')
2var h = require('mutant/h')
3var isString= require('lodash/isString')
4var maxBy= require('lodash/maxBy')
5var marksum = require('markdown-summary')
6var markdown = require('ssb-markdown')
7var ref = require('ssb-ref')
8var htmlEscape = require('html-escape')
9
10function renderEmoji (emoji, url) {
11 if (!url) return ':' + emoji + ':'
12 return `
13 <img
14 src="${htmlEscape(url)}"
15 alt=":${htmlEscape(emoji)}:"
16 title=":${htmlEscape(emoji)}:"
17 class="emoji"
18 >
19 `
20}
21
22exports.gives = nest('app.html.blogCard', true)
23
24exports.needs = nest({
25 'keys.sync.id': 'first',
26 'history.sync.push': 'first',
27 'about.obs.name': 'first',
28 'about.html.avatar': 'first',
29 'translations.sync.strings': 'first',
30 'unread.sync.isUnread': 'first',
31 // 'message.html.markdown': 'first',
32 'message.html.timeago': 'first',
33 'blob.sync.url': 'first',
34 'emoji.sync.url': 'first'
35})
36
37exports.create = function (api) {
38
39 //render markdown, but don't support patchwork@2 style mentions or custom emoji right now.
40 function render (source) {
41 return markdown.block(source, {
42 emoji: (emoji) => {
43 return renderEmoji(emoji, api.emoji.sync.url(emoji))
44 },
45 toUrl: (id) => {
46 if (ref.isBlob(id)) return api.blob.sync.url(id)
47 return id
48 },
49 imageLink: (id) => id
50 })
51 }
52
53
54 //render the icon for a blog.
55 //it would be more depjecty to split this
56 //into two methods, one in a private plugin
57 //one in a channel plugin
58 function blogIcon (msg) {
59 if(msg.value.private) {
60 const myId = api.keys.sync.id()
61
62 return msg.value.content.recps
63 .map(link => isString(link) ? link : link.link)
64 .filter(link => link !== myId)
65 .map(link => api.about.html.avatar)
66 }
67 else if(msg.value.content.channel)
68 return '#'+msg.value.content.channel
69 }
70
71
72 // REFACTOR: move this to a template?
73 function buildRecipientNames (blog) {
74 const myId = api.keys.sync.id()
75
76 return blog.value.content.recps
77 .map(link => isString(link) ? link : link.link)
78 .filter(link => link !== myId)
79 .map(api.about.obs.name)
80 }
81
82 return nest('app.html.blogCard', (blog, opts = {}) => {
83 var strings = api.translations.sync.strings()
84
85 if(!blog.value) return
86 if('string' !== typeof blog.value.content.text) return
87
88 const lastReply = blog.replies && maxBy(blog.replies, r => r.timestamp)
89
90 const goToBlog = () => api.history.sync.push(blog)
91 const onClick = opts.onClick || goToBlog
92 const id = `${blog.key.replace(/[^a-z0-9]/gi, '')}` //-${JSON.stringify(opts)}`
93 // id is only here to help morphdom morph accurately
94
95 const { content, author } = blog.value
96
97 var img = h('Thumbnail')
98 var m = /\!\[[^]+\]\(([^\)]+)\)/.exec(marksum.image(content.text))
99 if(m) {
100 //Hey this works! fit an image into a specific size (see blog-card.mcss)
101 //centered, and scaled to fit the square (works with both landscape and portrait!)
102 //This is functional css not opinionated css, so all embedded.
103 img.style = 'background-image: url("'+api.blob.sync.url(m[1])+'"); background-position:center; background-size: cover;'
104 }
105
106 const title = render(marksum.title(content.text))
107 const summary = render(marksum.summary(content.text))
108
109 const className = blog.unread ? '-unread': ''
110
111 return h('BlogCard', { id, className, 'ev-click': onClick }, [
112 h('div.context', [
113 api.about.html.avatar(author, 'tiny'),
114 h('div.name', api.about.obs.name(author)),
115 api.message.html.timeago(blog)
116 ]),
117 h('div.content', [
118 img,
119 h('div.text', [
120 h('h2', {innerHTML: title}),
121 content.channel
122 ? h('Button -channel', '#'+content.channel)
123 : '',
124 h('div.summary', {innerHTML: summary})
125 ])
126 ])
127 ])
128 })
129}
130
131

Built with git-ssb-web