git ssb

10+

Matt McKegg / patchwork



Tree: 9744d260b89e1e2afac37b36c0973c99040adefd

Files: 9744d260b89e1e2afac37b36c0973c99040adefd / modules / public.js

6081 bytesRaw
1var MutantMap = require('@mmckegg/mutant/map')
2var computed = require('@mmckegg/mutant/computed')
3var when = require('@mmckegg/mutant/when')
4var send = require('@mmckegg/mutant/send')
5var pull = require('pull-stream')
6var extend = require('xtend')
7
8var plugs = require('patchbay/plugs')
9var h = require('../lib/h')
10var message_compose = plugs.first(exports.message_compose = [])
11var sbot_log = plugs.first(exports.sbot_log = [])
12var sbot_feed = plugs.first(exports.sbot_feed = [])
13var sbot_user_feed = plugs.first(exports.sbot_user_feed = [])
14
15var feed_summary = plugs.first(exports.feed_summary = [])
16var obs_channels = plugs.first(exports.obs_channels = [])
17var obs_subscribed_channels = plugs.first(exports.obs_subscribed_channels = [])
18var get_id = plugs.first(exports.get_id = [])
19var publish = plugs.first(exports.sbot_publish = [])
20var obs_following = plugs.first(exports.obs_following = [])
21var obs_recently_updated_feeds = plugs.first(exports.obs_recently_updated_feeds = [])
22var avatar_image = plugs.first(exports.avatar_image = [])
23var avatar_name = plugs.first(exports.avatar_name = [])
24var obs_local = plugs.first(exports.obs_local = [])
25
26exports.screen_view = function (path, sbot) {
27 if (path === '/public') {
28 var id = get_id()
29 var channels = computed(obs_channels(), items => items.slice(0, 6), {comparer: arrayEq})
30 var subscribedChannels = obs_subscribed_channels(id)
31 var loading = computed(subscribedChannels.sync, x => !x)
32 var localPeers = obs_local()
33 var following = obs_following(id)
34
35 var oldest = Date.now() - (2 * 24 * 60 * 60e3)
36 getFirstMessage(id, (err, msg) => {
37 if (msg) {
38 // fall back to timestamp stream before this, give 48 hrs for feeds to stabilize
39 if (msg.value.timestamp > oldest) {
40 oldest = Date.now()
41 }
42 }
43 })
44
45 var whoToFollow = computed([obs_following(id), obs_recently_updated_feeds(200)], (following, recent) => {
46 return Array.from(recent).filter(x => x !== id && !following.has(x)).slice(0, 20)
47 })
48
49 return h('SplitView', [
50 h('div.side', [
51 h('h2', 'Active Channels'),
52 when(loading, [ h('Loading') ]),
53 h('ChannelList', {
54 hidden: loading
55 }, [
56 MutantMap(channels, (channel) => {
57 var subscribed = subscribedChannels.has(channel.id)
58 return h('a.channel', {
59 href: `##${channel.id}`,
60 classList: [
61 when(subscribed, '-subscribed')
62 ]
63 }, [
64 h('span.name', '#' + channel.id),
65 when(subscribed,
66 h('a -unsubscribe', {
67 'ev-click': send(unsubscribe, channel.id)
68 }, 'Unsubscribe'),
69 h('a -subscribe', {
70 'ev-click': send(subscribe, channel.id)
71 }, 'Subscribe')
72 )
73 ])
74 }, {maxTime: 5})
75 ]),
76
77 when(computed(localPeers, x => x.length), h('h2', 'Local')),
78 h('ProfileList', [
79 MutantMap(localPeers, (id) => {
80 return h('a.profile', {
81 href: `#${id}`
82 }, [
83 h('div.avatar', [avatar_image(id)]),
84 h('div.main', [
85 h('div.name', [ avatar_name(id) ])
86 ])
87 ])
88 })
89 ]),
90
91 when(computed(whoToFollow, x => x.length), h('h2', 'Who to follow')),
92 h('ProfileList', [
93 MutantMap(whoToFollow, (id) => {
94 return h('a.profile', {
95 href: `#${id}`
96 }, [
97 h('div.avatar', [avatar_image(id)]),
98 h('div.main', [
99 h('div.name', [ avatar_name(id) ])
100 ])
101 ])
102 })
103 ])
104 ]),
105 h('div.main', [
106 feed_summary(getFeed, [
107 message_compose({type: 'post'}, {placeholder: 'Write a public message'})
108 ], {
109 waitUntil: computed([
110 following.sync,
111 subscribedChannels.sync
112 ], x => x.every(Boolean)),
113 windowSize: 500,
114 filter: (item) => {
115 return (
116 id === item.author ||
117 following().has(item.author) ||
118 subscribedChannels().has(item.channel) ||
119 (item.repliesFrom && item.repliesFrom.has(id)) ||
120 item.digs && item.digs.has(id)
121 )
122 },
123 bumpFilter: (msg, group) => {
124 if (!group.message) {
125 return (
126 isMentioned(id, msg.value.content.mentions) ||
127 msg.value.author === id || (
128 fromDay(msg, group.fromTime) && (
129 following().has(msg.value.author) ||
130 group.repliesFrom.has(id)
131 )
132 )
133 )
134 }
135 return true
136 }
137 })
138 ])
139 ])
140 }
141
142 // scoped
143
144 function getFeed (opts) {
145 if (opts.lt && opts.lt < oldest) {
146 opts = extend(opts, {lt: parseInt(opts.lt, 10)})
147 console.log('using old feed', opts)
148 return pull(
149 sbot_feed(opts),
150 pull.map((msg) => {
151 if (msg.sync) {
152 return msg
153 } else {
154 return {key: msg.key, value: msg.value, timestamp: msg.value.timestamp}
155 }
156 })
157 )
158 } else {
159 return sbot_log(opts)
160 }
161 }
162}
163
164function fromDay (msg, fromTime) {
165 return (fromTime - msg.timestamp) < (24 * 60 * 60e3)
166}
167
168function isMentioned (id, list) {
169 if (Array.isArray(list)) {
170 return list.includes(id)
171 } else {
172 return false
173 }
174}
175
176function subscribe (id) {
177 publish({
178 type: 'channel',
179 channel: id,
180 subscribed: true
181 })
182}
183
184function unsubscribe (id) {
185 publish({
186 type: 'channel',
187 channel: id,
188 subscribed: false
189 })
190}
191
192function arrayEq (a, b) {
193 if (Array.isArray(a) && Array.isArray(b) && a.length === b.length && a !== b) {
194 return a.every((value, i) => value === b[i])
195 }
196}
197
198function getFirstMessage (feedId, cb) {
199 sbot_user_feed({id: feedId, gte: 0, limit: 1})(null, cb)
200}
201

Built with git-ssb-web