git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Tree: d2a64eaa0249b9f9b937741f6bb64eae15d044bd

Files: d2a64eaa0249b9f9b937741f6bb64eae15d044bd / modules / page / html / render / profile.js

8020 bytesRaw
1var nest = require('depnest')
2var ref = require('ssb-ref')
3var {h, when, computed, map, send, dictToCollection, resolve} = require('mutant')
4var extend = require('xtend')
5
6exports.needs = nest({
7 'about.obs': {
8 name: 'first',
9 names: 'first',
10 images: 'first',
11 color: 'first'
12 },
13 'blob.sync.url': 'first',
14 'blob.html.input': 'first',
15 'message.async.publish': 'first',
16 'about.html.image': 'first',
17 'feed.html.rollup': 'first',
18 'sbot.pull.userFeed': 'first',
19 'sbot.async.publish': 'first',
20 'keys.sync.id': 'first',
21 'sheet.display': 'first',
22 'contact.obs': {
23 followers: 'first',
24 following: 'first'
25 }
26})
27exports.gives = nest('page.html.render')
28
29exports.create = function (api) {
30 return nest('page.html.render', function profile (id) {
31 if (!ref.isFeed(id)) return
32
33 var name = api.about.obs.name(id)
34 var yourId = api.keys.sync.id()
35 var yourFollows = api.contact.obs.following(yourId)
36 var rawFollowers = api.contact.obs.followers(id)
37 var rawFollowing = api.contact.obs.following(id)
38 var friendsLoaded = computed([rawFollowers.sync, rawFollowing.sync], (...x) => x.every(Boolean))
39
40 var friends = computed([rawFollowing, rawFollowers], (following, followers) => {
41 return Array.from(following).filter(follow => followers.has(follow))
42 })
43
44 var following = computed([rawFollowing, friends], (following, friends) => {
45 return Array.from(following).filter(follow => !friends.includes(follow))
46 })
47
48 var followers = computed([rawFollowers, friends], (followers, friends) => {
49 return Array.from(followers).filter(follower => !friends.includes(follower))
50 })
51
52 var isFriends = computed([friends], function (friends) {
53 return friends.includes(yourId)
54 })
55
56 var followsYou = computed([following], function (followsYou) {
57 return followsYou.includes(yourId)
58 })
59
60 var youFollow = computed([yourFollows], function (youFollow) {
61 return youFollow.has(id)
62 })
63
64 var names = api.about.obs.names(id)
65 var images = api.about.obs.images(id)
66
67 var namePicker = h('div', {className: 'Picker'}, [
68 map(dictToCollection(names), (item) => {
69 var isSelf = computed(item.value, (ids) => ids.includes(id))
70 var isAssigned = computed(item.value, (ids) => ids.includes(yourId))
71 return h('a.name', {
72 'ev-click': () => {
73 if (!isAssigned()) {
74 assignName(id, resolve(item.key))
75 }
76 },
77 href: '#',
78 classList: [
79 when(isSelf, '-self'),
80 when(isAssigned, '-assigned')
81 ],
82 title: nameList(when(isSelf, 'Self Assigned', 'Assigned By'), item.value)
83 }, [
84 item.key
85 ])
86 }),
87 h('a -add', {
88 'ev-click': () => {
89 rename(id)
90 },
91 href: '#',
92 }, ['+'])
93 ])
94
95 var imagePicker = h('div', {className: 'Picker'}, [
96 map(dictToCollection(images), (item) => {
97 var isSelf = computed(item.value, (ids) => ids.includes(id))
98 var isAssigned = computed(item.value, (ids) => ids.includes(yourId))
99 return h('a.name', {
100 'ev-click': () => {
101 if (!isAssigned()) {
102 assignImage(id, resolve(item.key))
103 }
104 },
105 href: '#',
106 classList: [
107 when(isSelf, '-self'),
108 when(isAssigned, '-assigned')
109 ],
110 title: nameList(when(isSelf, 'Self Assigned', 'Assigned By'), item.value)
111 }, [
112 h('img', {
113 className: 'Avatar',
114 style: { 'background-color': api.about.obs.color(id) },
115 src: computed(item.key, api.blob.sync.url)
116 })
117 ])
118 }),
119 h('span.add', [
120 api.blob.html.input(file => {
121 assignImage(id, file.link)
122 }, {
123 accept: 'image/*',
124 resize: { width: 500, height: 500 }
125 })
126 ])
127 ])
128
129 var prepend = h('header', {className: 'ProfileHeader'}, [
130 h('div.image', api.about.html.image(id)),
131 h('div.main', [
132 h('div.title', [
133 h('h1', ['@', name]),
134 h('div.meta', [
135 when(id === yourId, [
136 h('a.ToggleButton.-disabled', 'This is you!')
137 ], [
138 when(youFollow,
139 h('a.ToggleButton.-unsubscribe', {
140 'href': '#',
141 'title': 'Click to unfollow',
142 'ev-click': send(unfollow, id)
143 }, when(isFriends, 'Friends', 'Following')),
144 h('a.ToggleButton.-subscribe', {
145 'href': '#',
146 'ev-click': send(follow, id)
147 }, when(followsYou, 'Follow Back', 'Follow'))
148 )
149 ])
150 ])
151 ]),
152 h('section', [ namePicker, imagePicker ])
153 ])
154 ])
155
156 var feedView = api.feed.html.rollup((opts) => {
157 return api.sbot.pull.userFeed(extend(opts, {id}))
158 }, { prepend })
159
160 var container = h('div', {className: 'SplitView'}, [
161 h('div.main', [
162 feedView
163 ]),
164 h('div.side.-right', [
165 when(friendsLoaded,
166 h('div', [
167 renderContactBlock('Friends', friends),
168 renderContactBlock('Followers', followers),
169 renderContactBlock('Following', following)
170 ]),
171 h('div', {className: 'Loading'})
172 )
173 ])
174 ])
175
176 container.pendingUpdates = feedView.pendingUpdates
177 container.reload = feedView.reload
178 return container
179 })
180
181 function renderContactBlock (title, profiles) {
182 return [
183 when(computed(profiles, x => x.length), h('h2', title)),
184 h('div', {
185 classList: 'ProfileList'
186 }, [
187 map(profiles, (id) => {
188 return h('a.profile', {
189 href: id
190 }, [
191 h('div.avatar', [api.about.html.image(id)]),
192 h('div.main', [
193 h('div.name', [ '@', api.about.obs.name(id) ])
194 ])
195 ])
196 }, {
197 idle: true
198 })
199 ])
200 ]
201 }
202
203 function follow (id) {
204 api.sbot.async.publish({
205 type: 'contact',
206 contact: id,
207 following: true
208 })
209 }
210
211 function unfollow (id) {
212 api.sbot.async.publish({
213 type: 'contact',
214 contact: id,
215 following: false
216 })
217 }
218
219 function assignImage (id, image) {
220 api.message.async.publish({
221 type: 'about',
222 about: id,
223 image
224 })
225 }
226
227 function assignName (id, name) {
228 api.message.async.publish({
229 type: 'about',
230 about: id,
231 name
232 })
233 }
234
235 function rename (id) {
236 api.sheet.display(close => {
237 var currentName = api.about.obs.name(id)
238 var input = h('input', {
239 style: {'font-size': '150%'},
240 value: currentName()
241 })
242 setTimeout(() => {
243 input.focus()
244 input.select()
245 }, 5)
246 return {
247 content: h('div', {
248 style: {
249 padding: '20px',
250 'text-align': 'center'
251 }
252 }, [
253 h('h2', {
254 style: {
255 'font-weight': 'normal'
256 }
257 }, ['What whould you like to call ', h('strong', ['@', currentName]), '?']),
258 input
259 ]),
260 footer: [
261 h('button -save', {
262 'ev-click': () => {
263 if (input.value.trim() && input.value !== currentName()) {
264 // no confirm
265 api.sbot.async.publish({
266 type: 'about',
267 about: id,
268 name: input.value.trim()
269 })
270 }
271 close()
272 }
273 }, 'Confirm'),
274 h('button -cancel', {
275 'ev-click': close
276 }, 'Cancel')
277 ]
278 }
279 })
280 }
281
282 function nameList (prefix, ids) {
283 var items = map(ids, api.about.obs.name)
284 return computed([prefix, items], (prefix, names) => {
285 return (prefix ? (prefix + '\n') : '') + names.map((n) => `- ${n}`).join('\n')
286 })
287 }
288}
289

Built with git-ssb-web