git ssb

0+

alanz / patchwork



forked from Matt McKegg / patchwork

Tree: a9d64b445268934597b0f1a9bcc2c433e1d994c0

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

5779 bytesRaw
1var nest = require('depnest')
2var ref = require('ssb-ref')
3var {Value, h, when, computed, map, send, dictToCollection} = 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 'about.html.image': 'first',
15 'feed.html.rollup': 'first',
16 'sbot.pull.userFeed': 'first',
17 'sbot.async.publish': 'first',
18 'keys.sync.id': 'first',
19 'profile.obs': {
20 followers: 'first',
21 following: 'first',
22 names: 'first'
23 }
24})
25exports.gives = nest('page.html.render')
26
27exports.create = function (api) {
28 return nest('page.html.render', function profile (id) {
29 if (!ref.isFeed(id)) return
30
31 var name = api.about.obs.name(id)
32 var yourId = api.keys.sync.id()
33 var yourFollows = api.profile.obs.following(yourId)
34 var rawFollowers = api.profile.obs.followers(id)
35 var rawFollowing = api.profile.obs.following(id)
36 var doneWaiting = Value(false)
37 setTimeout(() => doneWaiting.set(true), 1e3)
38 var friendsLoaded = computed([rawFollowers, rawFollowing, doneWaiting], (...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 classList: [
73 when(isSelf, '-self'),
74 when(isAssigned, '-assigned')
75 ],
76 title: nameList(when(isSelf, 'Self Assigned', 'Assigned By'), item.value)
77 }, [
78 item.key
79 ])
80 })
81 ])
82
83 var imagePicker = h('div', {className: 'Picker'}, [
84 map(dictToCollection(images), (item) => {
85 var isSelf = computed(item.value, (ids) => ids.includes(id))
86 var isAssigned = computed(item.value, (ids) => ids.includes(yourId))
87 return h('a.name', {
88 classList: [
89 when(isSelf, '-self'),
90 when(isAssigned, '-assigned')
91 ],
92 title: nameList(when(isSelf, 'Self Assigned', 'Assigned By'), item.value)
93 }, [
94 h('img', {
95 className: 'Avatar',
96 style: { 'background-color': api.about.obs.color(id) },
97 src: computed(item.key, api.blob.sync.url)
98 })
99 ])
100 })
101 ])
102
103 var prepend = h('header', {className: 'ProfileHeader'}, [
104 h('div.image', api.about.html.image(id)),
105 h('div.main', [
106 h('div.title', [
107 h('h1', ['@', name]),
108 h('div.meta', [
109 when(id === yourId, [
110 h('a.-disabled', 'This is you!')
111 ], [
112 when(youFollow,
113 h('a.ToggleButton.-unsubscribe', {
114 'href': '#',
115 'title': 'Click to unfollow',
116 'ev-click': send(unfollow, id)
117 }, when(isFriends, 'Friends', 'Following')),
118 h('a.ToggleButton.-subscribe', {
119 'href': '#',
120 'ev-click': send(follow, id)
121 }, when(followsYou, 'Follow Back', 'Follow'))
122 )
123 ])
124 ])
125 ]),
126 h('section', [ namePicker, imagePicker ])
127 ])
128 ])
129
130 return h('div', {className: 'SplitView'}, [
131 h('div.main', [
132 api.feed.html.rollup((opts) => {
133 return api.sbot.pull.userFeed(extend(opts, {id}))
134 }, { prepend })
135 ]),
136 h('div.side.-right', [
137 when(friendsLoaded,
138 h('div', [
139 renderContactBlock('Friends', friends),
140 renderContactBlock('Followers', followers),
141 renderContactBlock('Following', following)
142 ]),
143 h('div', {className: 'Loading'})
144 )
145 ])
146 ])
147 })
148
149 function renderContactBlock (title, profiles) {
150 return [
151 when(computed(profiles, x => x.length), h('h2', title)),
152 h('div', {
153 classList: 'ProfileList'
154 }, [
155 map(profiles, (id) => {
156 return h('a.profile', {
157 href: id
158 }, [
159 h('div.avatar', [api.about.html.image(id)]),
160 h('div.main', [
161 h('div.name', [ '@', api.about.obs.name(id) ])
162 ])
163 ])
164 }, {
165 idle: true
166 })
167 ])
168 ]
169 }
170
171 function follow (id) {
172 api.sbot.async.publish({
173 type: 'contact',
174 contact: id,
175 following: true
176 })
177 }
178
179 function unfollow (id) {
180 api.sbot.async.publish({
181 type: 'contact',
182 contact: id,
183 following: false
184 })
185 }
186
187 function nameList (prefix, ids) {
188 var items = map(ids, api.about.obs.name)
189 return computed([prefix, items], (prefix, names) => {
190 return (prefix ? (prefix + '\n') : '') + names.map((n) => `- ${n}`).join('\n')
191 })
192 }
193}
194

Built with git-ssb-web