git ssb

10+

Matt McKegg / patchwork



Tree: 6975c466bb35703e5c76fdd5fef5a2d91e216d4b

Files: 6975c466bb35703e5c76fdd5fef5a2d91e216d4b / modules / page / html / render / public.js

6952 bytesRaw
1var nest = require('depnest')
2var { h, send, when, computed, map } = require('mutant')
3
4exports.needs = nest({
5 sbot: {
6 obs: {
7 connectedPeers: 'first',
8 localPeers: 'first'
9 }
10 },
11 'feed.pull.public': 'first',
12 'about.html.image': 'first',
13 'about.obs.name': 'first',
14 'invite.sheet': 'first',
15
16 'message.html.compose': 'first',
17 'message.async.publish': 'first',
18 'progress.html.peer': 'first',
19
20 'feed.html.rollup': 'first',
21 'profile.obs.recentlyUpdated': 'first',
22 'contact.obs.following': 'first',
23 'channel.obs': {
24 subscribed: 'first',
25 recent: 'first'
26 },
27 'keys.sync.id': 'first'
28})
29
30exports.gives = nest({
31 'page.html.render': true
32})
33
34exports.create = function (api) {
35 return nest('page.html.render', page)
36
37 function page (path) {
38 if (path !== '/public') return // "/" is a sigil for "page"
39
40 var id = api.keys.sync.id()
41 var following = api.contact.obs.following(id)
42 var subscribedChannels = api.channel.obs.subscribed(id)
43 var recentChannels = api.channel.obs.recent()
44 var loading = computed([subscribedChannels.sync, recentChannels.sync], (...args) => !args.every(Boolean))
45 var channels = computed(recentChannels, items => items.slice(0, 8), {comparer: arrayEq})
46 var connectedPeers = api.sbot.obs.connectedPeers()
47 var localPeers = api.sbot.obs.localPeers()
48 var connectedPubs = computed([connectedPeers, localPeers], (c, l) => c.filter(x => !l.includes(x)))
49
50 var prepend = [
51 api.message.html.compose({ meta: { type: 'post' }, placeholder: 'Write a public message' })
52 ]
53
54 var feedView = api.feed.html.rollup(api.feed.pull.public, {
55 prepend,
56 waitFor: computed([
57 following.sync,
58 subscribedChannels.sync
59 ], (...x) => x.every(Boolean)),
60 windowSize: 1000,
61 filter: (item) => {
62 return !item.boxed && (item.lastUpdateType !== 'post' || item.message) && (
63 id === item.author ||
64 (item.author && following().has(item.author)) ||
65 (item.type === 'message' && subscribedChannels().has(item.channel)) ||
66 (item.type === 'subscribe' && item.subscribers.size) ||
67 (item.repliesFrom && item.repliesFrom.has(id)) ||
68 item.likes && item.likes.has(id)
69 )
70 },
71 bumpFilter: (msg, group) => {
72 if (group.type === 'subscribe') {
73 removeStrangers(group.subscribers)
74 }
75
76 if (group.type === 'message') {
77 removeStrangers(group.likes)
78 removeStrangers(group.repliesFrom)
79
80 if (!group.message) {
81 // if message is old, only show replies from friends
82 group.replies = group.replies.filter(x => {
83 return (x.value.author === id || following().has(x.value.author))
84 })
85 }
86 }
87
88 if (!group.message) {
89 return (
90 isMentioned(id, msg.value.content.mentions) ||
91 msg.value.author === id || (
92 fromDay(msg, group.fromTime) && (
93 following().has(msg.value.author) ||
94 group.repliesFrom.has(id)
95 )
96 )
97 )
98 }
99 return true
100 }
101 })
102
103 var result = h('div.SplitView', [
104 h('div.side', [
105 getSidebar()
106 ]),
107 h('div.main', feedView)
108 ])
109
110 result.pendingUpdates = feedView.pendingUpdates
111 result.reload = feedView.reload
112
113 return result
114
115 function removeStrangers (set) {
116 if (set) {
117 Array.from(set).forEach(key => {
118 if (!following().has(key) && key !== id) {
119 set.delete(key)
120 }
121 })
122 }
123 }
124
125 function getSidebar () {
126 var whoToFollow = computed([following, api.profile.obs.recentlyUpdated(), localPeers], (following, recent, peers) => {
127 return Array.from(recent).filter(x => x !== id && !following.has(x) && !peers.includes(x)).slice(0, 10)
128 })
129 return [
130 h('button -pub -full', {
131 'ev-click': api.invite.sheet
132 }, '+ Join Pub'),
133 when(computed(channels, x => x.length), h('h2', 'Active Channels')),
134 when(loading, [ h('Loading') ]),
135 h('div', {
136 classList: 'ChannelList',
137 hidden: loading
138 }, [
139 map(channels, (channel) => {
140 var subscribed = subscribedChannels.has(channel)
141 return h('a.channel', {
142 href: `#${channel}`,
143 classList: [
144 when(subscribed, '-subscribed')
145 ]
146 }, [
147 h('span.name', '#' + channel),
148 when(subscribed,
149 h('a.-unsubscribe', {
150 'ev-click': send(unsubscribe, channel)
151 }, 'Unsubscribe'),
152 h('a.-subscribe', {
153 'ev-click': send(subscribe, channel)
154 }, 'Subscribe')
155 )
156 ])
157 }, {maxTime: 5}),
158 h('a.channel -more', {href: '/channels'}, 'More Channels...')
159 ]),
160
161 PeerList(localPeers, 'Local'),
162 PeerList(connectedPubs, 'Connected Pubs'),
163
164 when(computed(whoToFollow, x => x.length), h('h2', 'Who to follow')),
165 when(following.sync,
166 h('div', {
167 classList: 'ProfileList'
168 }, [
169 map(whoToFollow, (id) => {
170 return h('a.profile', {
171 href: id
172 }, [
173 h('div.avatar', [api.about.html.image(id)]),
174 h('div.main', [
175 h('div.name', [ api.about.obs.name(id) ])
176 ])
177 ])
178 })
179 ])
180 )
181 ]
182 }
183
184 function PeerList (ids, title) {
185 return [
186 when(computed(ids, x => x.length), h('h2', title)),
187 h('div', {
188 classList: 'ProfileList'
189 }, [
190 map(ids, (id) => {
191 return h('a.profile', {
192 classList: [ '-connected' ],
193 href: id
194 }, [
195 h('div.avatar', [api.about.html.image(id)]),
196 h('div.main', [
197 h('div.name', [ api.about.obs.name(id) ])
198 ]),
199 h('div.progress', [
200 api.progress.html.peer(id)
201 ])
202 ])
203 })
204 ])
205 ]
206 }
207
208 function subscribe (id) {
209 api.message.async.publish({
210 type: 'channel',
211 channel: id,
212 subscribed: true
213 })
214 }
215
216 function unsubscribe (id) {
217 api.message.async.publish({
218 type: 'channel',
219 channel: id,
220 subscribed: false
221 })
222 }
223 }
224}
225
226function isMentioned (id, list) {
227 if (Array.isArray(list)) {
228 return list.includes(id)
229 } else {
230 return false
231 }
232}
233
234function fromDay (msg, fromTime) {
235 return (fromTime - msg.timestamp) < (24 * 60 * 60e3)
236}
237
238function arrayEq (a, b) {
239 if (Array.isArray(a) && Array.isArray(b) && a.length === b.length && a !== b) {
240 return a.every((value, i) => value === b[i])
241 }
242}
243

Built with git-ssb-web