git ssb

5+

Matt McKegg / ferment



Tree: 286f58e95fb08e5233963b593bb28cd72bf2655a

Files: 286f58e95fb08e5233963b593bb28cd72bf2655a / views / audio-post.js

5462 bytesRaw
1var h = require('../lib/h')
2var MutantMap = require('@mmckegg/mutant/map')
3var computed = require('@mmckegg/mutant/computed')
4var when = require('@mmckegg/mutant/when')
5var renderMiniProfile = require('../widgets/mini-profile')
6var contextMenu = require('../lib/context-menu')
7var magnet = require('magnet-uri')
8var send = require('@mmckegg/mutant/send')
9var AudioOverview = require('../widgets/audio-overview')
10var markdown = require('../lib/markdown')
11var colorHash = require('../lib/color-hash')
12var humanTime = require('human-time')
13var TorrentStatusWidget = require('../widgets/torrent-status')
14
15module.exports = AudioPostView
16
17function AudioPostView (context, postId) {
18 var post = context.api.getPost(postId)
19 var rankedLikedIds = context.api.rankProfileIds(post.likes, 12)
20 var likes = MutantMap(rankedLikedIds, id => context.api.getProfile(id))
21 var likesCount = computed(post.likes, (list) => list.length)
22 var repostsCount = computed(post.reposters, (list) => list.length)
23 var player = context.player
24 var infoHash = computed(post.audioSrc, (src) => magnet.decode(src).infoHash)
25 var profile = context.api.getProfile(context.api.id)
26 var reposted = computed([profile.posts, post.id], (posts, id) => posts.includes(id))
27 var liked = computed([profile.likes, postId], (likes, id) => likes.includes(id))
28 var isOwner = context.api.id === post.author.id
29 var color = colorHash.hex(postId)
30
31 var url = computed(post.artworkSrc, context.api.getBlobUrl)
32
33 return h('AudioPostView', {
34 'ev-contextmenu': contextMenu.bind(null, context, post),
35 classList: [
36 computed(post.state, (s) => `-${s}`)
37 ]
38 }, [
39 h('header', [
40 h('div.main', [
41 h('div.title', [
42 h('a.play', { 'ev-click': send(player.togglePlay, post), href: '#' }),
43 h('header', [
44 h('a.feedTitle', {
45 href: '#', 'ev-click': send(context.actions.viewProfile, post.author.id)
46 }, [post.author.displayName]), h('br'),
47 h('span.title', [post.title])
48 ]),
49 h('div.timestamp', [
50 humanTime(Date.now() / 1000 - post.timestamp() / 1000)
51 ])
52 ]),
53 h('div.display', {
54 hooks: [
55 SetPositionHook(context, post)
56 ]
57 }, [
58 AudioOverview(post.overview, 600, 100),
59 h('div.progress', {
60 style: {
61 width: computed([post.position, post.duration], (pos, dur) => Math.round(pos / dur * 1000) / 10 + '%')
62 }
63 }),
64 when(post.position, h('span.position', computed(post.position, formatTime))),
65 h('span.duration', computed(post.duration, formatTime))
66 ]),
67 h('div.options', [
68 h('a.like', {
69 href: '#',
70 'ev-click': send(toggleLike, { liked, context, post }),
71 classList: [
72 when(liked, '-active')
73 ]
74 }, [
75 '๐Ÿ’š ', when(likesCount, likesCount, 'Like')
76 ]),
77 when(isOwner,
78 h('a.repost -disabled', [
79 '๐Ÿ“ก ', when(repostsCount, repostsCount, 'Repost')
80 ]),
81 h('a.repost', {
82 href: '#',
83 'ev-click': send(toggleRepost, { reposted, context, post }),
84 classList: [
85 when(reposted, '-active')
86 ]
87 }, [
88 '๐Ÿ“ก ', when(repostsCount, repostsCount, 'Repost')
89 ])
90 ),
91 when(isOwner,
92 h('a.edit', { href: '#', 'ev-click': edit }, 'โœจ Edit')
93 ),
94 h('a.save', { href: '#', 'ev-click': send(context.actions.saveFile, post) }, '๐Ÿ’พ Save'),
95 TorrentStatusWidget(context, infoHash)
96 ])
97 ]),
98
99 h('div.artwork', { style: {
100 'background-image': computed(url, (src) => src ? `url("${src}")` : ''),
101 'background-color': color
102 }})
103 ]),
104 h('section', [
105 h('div.main', [
106 markdown(post.description)
107 ]),
108 h('div.side', [
109 when(likesCount, [
110 h('h2', ['Liked by ', h('span.sub', [likesCount])]),
111 MutantMap(likes, (item) => renderMiniProfile(context, item), { maxTime: 5 })
112 ])
113 ])
114 ])
115 ])
116
117 // scoped
118
119 function edit () {
120 context.actions.editPost({
121 id: post.id,
122 item: post()
123 })
124 }
125}
126
127function percent (value) {
128 return Math.round(value * 100) + '%'
129}
130
131function toggleLike (opts) {
132 if (opts.liked()) {
133 opts.context.api.unlike(opts.post.id)
134 } else {
135 opts.context.api.like(opts.post.id)
136 }
137}
138
139function toggleRepost (opts) {
140 if (opts.reposted()) {
141 opts.context.api.unrepost(opts.post.id)
142 } else {
143 opts.context.api.repost(opts.post.id)
144 }
145}
146
147function SetPositionHook (context, item) {
148 return function (element) {
149 element.onmousemove = element.onmousedown = function (ev) {
150 if (ev.buttons && ev.button === 0) {
151 var box = ev.currentTarget.getBoundingClientRect()
152 var x = ev.clientX - box.left
153 if (x < 5) {
154 x = 0
155 }
156 setPosition(x / box.width * item.duration())
157 }
158 }
159 }
160
161 function setPosition (position) {
162 if (context.player.currentItem.get() === item) {
163 context.player.audioElement.currentTime = position
164 }
165 item.position.set(position)
166 }
167}
168
169function formatTime (value) {
170 var minutes = Math.floor(value / 60)
171 var seconds = Math.floor(value % 60)
172 return minutes + ':' + ('0' + seconds).slice(-2)
173}
174

Built with git-ssb-web