git ssb

10+

Matt McKegg / patchwork



Tree: a55c6ee357ae26944dcd50814406be4d91d90804

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

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

Built with git-ssb-web