git ssb

16+

Dominic / patchbay



Tree: 2972c01e2f9a546bca5ea959b8278720b94da3c4

Files: 2972c01e2f9a546bca5ea959b8278720b94da3c4 / contact / html / relationships.js

4982 bytesRaw
1const nest = require('depnest')
2const { h, map, computed, when, Value } = require('mutant')
3
4exports.gives = nest('contact.html.relationships')
5
6exports.needs = nest({
7 // 'about.html.image': 'first',
8 'about.html.avatar': 'first',
9 // 'about.obs.name': 'first',
10 'contact.async.follow': 'first',
11 'contact.async.unfollow': 'first',
12 'contact.async.block': 'first',
13 'contact.async.unblock': 'first',
14 'contact.obs.followers': 'first',
15 'contact.obs.following': 'first',
16 'contact.obs.blockers': 'first',
17 'contact.obs.blocking': 'first',
18 'keys.sync.id': 'first'
19})
20
21exports.create = function (api) {
22 return nest({
23 'contact.html.relationships': relationships
24 })
25
26 function relationships (feedId) {
27 const rawFollowing = api.contact.obs.following(feedId)
28 const rawFollowers = api.contact.obs.followers(feedId)
29
30 // mix: TODO rework this
31 const friends = computed([rawFollowing, rawFollowers], (following, followers) => {
32 return [...following].filter(follow => followers.includes(follow))
33 })
34 const following = computed([rawFollowing, friends], (following, friends) => {
35 return [...following].filter(follow => !friends.includes(follow))
36 })
37 const followers = computed([rawFollowers, friends], (followers, friends) => {
38 return [...followers].filter(follower => !friends.includes(follower))
39 })
40 const blockers = api.contact.obs.blockers(feedId)
41 const blocking = api.contact.obs.blocking(feedId)
42
43 const modes = [
44 { label: 'Friends', data: friends },
45 { label: 'Follows', data: following },
46 { label: 'Followers', data: followers },
47 { label: 'Blocked by', data: blockers, hideEmpty: true },
48 { label: 'Blocking', data: blocking, hideEmpty: true }
49 ]
50 const mode = Value(0)
51 const setMode = (i) => {
52 if (mode() === i) mode.set()
53 else mode.set(i)
54 }
55
56 return h('Relationships', [
57 h('header', 'Relationships'),
58 RelationshipStatus({ feedId, rawFollowing, blockers, api }),
59
60 h('div.groups', [
61 h('div.tabs', modes.map(({ label, data, hideEmpty }, i) => {
62 return computed([data, mode], (d, mode) => {
63 if (hideEmpty && !d.length) return
64
65 return h('div.tab',
66 {
67 className: mode === i ? '-active' : '',
68 'ev-click': () => setMode(i)
69 },
70 [
71 h('div.label', label),
72 h('div.count', d.length > 50 ? '50+' : d.length)
73 ]
74 )
75 })
76 })),
77 h('div.group', computed(mode, i => {
78 if (i === null) return
79
80 const { data } = modes[i]
81 // NOTE - there's a race condition where putting a breakpoint here
82 // gives the cache time to load or something?
83 // INTERMITENT BUG perhaps with api.contacts.obs ?
84 return map(data, api.about.html.avatar)
85 }))
86 ])
87 ])
88 }
89}
90
91function RelationshipStatus ({ feedId, rawFollowing, blockers, api }) {
92 const myId = api.keys.sync.id()
93 if (feedId === myId) return
94
95 // mix: TODO oh lord this is ugly, refactor it !
96 const ImFollowing = api.contact.obs.following(myId)
97 const IFollowThem = computed([ImFollowing], ImFollowing => ImFollowing.includes(feedId))
98 const theyFollowMe = computed([rawFollowing], following => following.includes(myId))
99 const ImBlockingThem = computed(blockers, blockers => blockers.includes(myId))
100
101 const relationshipStatus = computed([IFollowThem, theyFollowMe], (IFollowThem, theyFollowMe) => {
102 return IFollowThem && theyFollowMe ? '- you are friends'
103 : IFollowThem ? '- you follow them'
104 : theyFollowMe ? '- they follow you'
105 : ''
106 })
107 const { unfollow, follow, block, unblock } = api.contact.async
108
109 return h('div.relationship-status', [
110 h('section -friendship', [
111 when(ImFollowing.sync,
112 when(IFollowThem,
113 h('button', { 'ev-click': () => unfollow(feedId) }, 'Unfollow'),
114 h('button', { 'ev-click': () => follow(feedId) }, 'Follow')
115 ),
116 h('button', { disabled: 'disabled' }, 'Loading...')
117 ),
118 when(ImFollowing.sync, h('div.relationship-status', relationshipStatus))
119 ]),
120 h('section -blocking', [
121 when(ImBlockingThem,
122 h('button -subtle', { 'ev-click': () => unblock(feedId, console.log) }, [ h('i.fa.fa-ban'), 'unblock' ]),
123 h('button -subtle', { 'ev-click': () => block(feedId, console.log) }, [ h('i.fa.fa-ban'), 'BLOCK' ])
124 ),
125 h('div.explainer', [
126 "Blocking tells everyone you don't want to communicate with a person.",
127 h('ul', [
128 h('li', 'You will no longer receive messages from this person'),
129 h('li', "This person won't get any new information about you (including this block)"),
130 h('li', "Your followers will see you have blocked this person - their apps need to know so that they don't pass your information on.")
131 ])
132 ])
133 ])
134 ])
135}
136

Built with git-ssb-web