Files: 9899c393ca4253f2d31fa840a2aa4733dc2dc99d / views.js
10789 bytesRaw
1 | var pull = require('pull-stream') |
2 | var human = require('human-time') |
3 | var sbot = require('./scuttlebot') |
4 | var hyperscroll = require('hyperscroll') |
5 | var More = require('pull-more') |
6 | var stream = require('hyperloadmore/stream') |
7 | var h = require('hyperscript') |
8 | var render = require('./render') |
9 | var ref = require('ssb-ref') |
10 | var client = require('ssb-client') |
11 | |
12 | var Next = require('pull-next-query') |
13 | |
14 | var config = require('./config')() |
15 | |
16 | var tools = require('./tools') |
17 | var avatar = require('./avatar') |
18 | var id = require('./keys').id |
19 | |
20 | var ssbKeys = require('ssb-keys') |
21 | var keys = require('./keys') |
22 | |
23 | var checkInvite = require('./invite') |
24 | |
25 | var compose = require('./compose') |
26 | |
27 | var about = function () { |
28 | var screen = document.getElementById('screen') |
29 | |
30 | var about = require('./about') |
31 | |
32 | var content = h('div.content', about) |
33 | |
34 | screen.appendChild(hyperscroll(content)) |
35 | } |
36 | |
37 | var privateStream = function () { |
38 | var content = h('div.content') |
39 | var screen = document.getElementById('screen') |
40 | screen.appendChild(hyperscroll(content)) |
41 | |
42 | function createStream (opts) { |
43 | return pull( |
44 | More(sbot.createLogStream, opts), |
45 | pull.filter(function (msg) { |
46 | return 'string' == typeof msg.value.content |
47 | }), |
48 | pull.filter(function (msg) { |
49 | var unboxed = ssbKeys.unbox(msg.value.content, keys) |
50 | if (unboxed) { |
51 | msg.value.content = unboxed |
52 | msg.value.private = true |
53 | return msg |
54 | } |
55 | }), |
56 | pull.map(function (msg) { |
57 | return render(msg) |
58 | }) |
59 | ) |
60 | } |
61 | |
62 | pull( |
63 | createStream({old: false, limit: 1000}), |
64 | stream.top(content) |
65 | ) |
66 | |
67 | pull( |
68 | createStream({reverse: true, live: false, limit: 1000}), |
69 | stream.bottom(content) |
70 | ) |
71 | } |
72 | |
73 | var mentionsStream = function () { |
74 | var content = h('div.content') |
75 | |
76 | var screen = document.getElementById('screen') |
77 | |
78 | screen.appendChild(hyperscroll(content)) |
79 | |
80 | function createStream (opts) { |
81 | return pull( |
82 | Next(sbot.backlinks, opts, ['value', 'timestamp']), |
83 | pull.map(function (msg) { |
84 | if (msg.value.private == true) return |
85 | return render(msg) |
86 | }) |
87 | ) |
88 | } |
89 | |
90 | pull( |
91 | createStream({ |
92 | limit: 10, |
93 | reverse: true, |
94 | index: 'DTA', |
95 | live: false, |
96 | query: [{$filter: {dest: id}}] |
97 | }), |
98 | stream.bottom(content) |
99 | ) |
100 | |
101 | pull( |
102 | createStream({ |
103 | limit: 10, |
104 | old: false, |
105 | index: 'DTA', |
106 | live: true, |
107 | query: [{$filter: {dest: id}}] |
108 | }), |
109 | stream.top(content) |
110 | ) |
111 | } |
112 | |
113 | var userStream = function (src) { |
114 | var content = h('div.content') |
115 | var screen = document.getElementById('screen') |
116 | screen.appendChild(hyperscroll(content)) |
117 | function createStream (opts) { |
118 | return pull( |
119 | More(sbot.userStream, opts, ['value', 'sequence']), |
120 | pull.map(function (msg) { |
121 | return render(msg) |
122 | }) |
123 | ) |
124 | } |
125 | |
126 | pull( |
127 | createStream({old: false, limit: 10, id: src}), |
128 | stream.top(content) |
129 | ) |
130 | |
131 | pull( |
132 | createStream({reverse: true, live: false, limit: 10, id: src}), |
133 | stream.bottom(content) |
134 | ) |
135 | |
136 | var profile = h('div.content#profile', h('div.message')) |
137 | |
138 | if (screen.firstChild.firstChild) { |
139 | screen.firstChild.insertBefore(profile, screen.firstChild.firstChild) |
140 | } else { |
141 | screen.firstChild.appendChild(profile) |
142 | } |
143 | var name = avatar.name(src) |
144 | |
145 | var editname = h('span', |
146 | avatar.name(src), |
147 | h('button.btn', 'Edit', { |
148 | onclick: function () { |
149 | var nameput = h('input', {placeholder: name.textContent}) |
150 | var nameedit = |
151 | h('span', nameput, |
152 | h('button.btn', 'Preview', { |
153 | onclick: function () { |
154 | if (nameput.value[0] != '@') |
155 | tobename = nameput.value |
156 | else |
157 | tobename = nameput.value.substring(1, 100) |
158 | var newname = h('span', h('a', {href: '#' + src}, '@' + tobename), h('button.btn', 'Publish', { |
159 | onclick: function () { |
160 | var donename = h('span', h('a', {href: '#' + src}, '@' + tobename)) |
161 | sbot.publish({type: 'about', about: src, name: tobename}) |
162 | localStorage[src + 'name'] = tobename |
163 | newname.parentNode.replaceChild(donename, newname) |
164 | } |
165 | })) |
166 | nameedit.parentNode.replaceChild(newname, nameedit) |
167 | } |
168 | }) |
169 | ) |
170 | editname.parentNode.replaceChild(nameedit, editname) |
171 | } |
172 | }) |
173 | ) |
174 | |
175 | var avatars = h('div.avatars', |
176 | h('a', {href: '#' + src}, |
177 | h('span.avatar--medium', avatar.image(src)), |
178 | editname |
179 | ) |
180 | ) |
181 | |
182 | pull( |
183 | sbot.userStream({id: src, reverse: false, limit: 1}), |
184 | pull.drain(function (msg) { |
185 | var howlong = h('span', h('br'), ' arrived ', human(new Date(msg.value.timestamp))) |
186 | avatars.appendChild(howlong) |
187 | console.log(msg) |
188 | }) |
189 | ) |
190 | |
191 | |
192 | var buttons = h('div.buttons') |
193 | |
194 | profile.firstChild.appendChild(avatars) |
195 | profile.firstChild.appendChild(buttons) |
196 | buttons.appendChild(tools.mute(src)) |
197 | |
198 | var writeMessage = h('button.btn', 'Public message ', avatar.name(src), { |
199 | onclick: function () { |
200 | opts = {} |
201 | opts.type = 'post' |
202 | opts.mentions = '[' + name.textContent + '](' + src + ')' |
203 | var composer = h('div#composer', h('div.message', compose(opts))) |
204 | profile.appendChild(composer) |
205 | } |
206 | }) |
207 | |
208 | var writePrivate = h('button.btn', 'Private message ', avatar.name(src), { |
209 | onclick: function () { |
210 | opts = {} |
211 | opts.type = 'post' |
212 | opts.mentions = '[' + name.textContent + '](' + src + ')' |
213 | opts.recps = [src, id] |
214 | var composer = h('div#composer', h('div.message', compose(opts))) |
215 | profile.appendChild(composer) |
216 | } |
217 | }) |
218 | |
219 | buttons.appendChild(writeMessage) |
220 | buttons.appendChild(writePrivate) |
221 | buttons.appendChild(tools.follow(src)) |
222 | |
223 | profile.firstChild.appendChild(tools.getFollowing(src)) |
224 | profile.firstChild.appendChild(tools.getFollowers(src)) |
225 | } |
226 | |
227 | var msgThread = function (src) { |
228 | |
229 | var content = h('div.content') |
230 | var screen = document.getElementById('screen') |
231 | screen.appendChild(hyperscroll(content)) |
232 | |
233 | pull( |
234 | sbot.query({query: [{$filter: { value: { content: {root: src}, timestamp: { $gt: 1 }}}}], live: true}), |
235 | pull.drain(function (msg) { |
236 | if (msg.value) { |
237 | content.appendChild(render(msg)) |
238 | } |
239 | }) |
240 | ) |
241 | |
242 | sbot.get(src, function (err, data) { |
243 | if (err) {console.log('could not find message')} |
244 | data.value = data |
245 | data.key = src |
246 | console.log(data) |
247 | var rootMsg = render(data) |
248 | |
249 | if (content.firstChild) { |
250 | content.insertBefore(rootMsg, content.firstChild) |
251 | } else { |
252 | content.appendChild(rootMsg) |
253 | } |
254 | }) |
255 | } |
256 | |
257 | var keyPage = function () { |
258 | var screen = document.getElementById('screen') |
259 | |
260 | var importKey = h('textarea.import', {placeholder: 'Import a new public/private key', name: 'textarea', style: 'width: 97%; height: 100px;'}) |
261 | |
262 | var content = h('div.content', |
263 | h('div.message#key', |
264 | h('h1', 'Your Key'), |
265 | h('p', {innerHTML: 'Your public/private key is: <pre><code>' + localStorage[config.caps.shs + '/secret'] + '</code></pre>'}, |
266 | h('button.btn', {onclick: function (e){ |
267 | localStorage[config.caps.shs +'/secret'] = '' |
268 | alert('Your public/private key has been deleted') |
269 | e.preventDefault() |
270 | location.hash = "" |
271 | location.reload() |
272 | }}, 'Delete Key') |
273 | ), |
274 | h('hr'), |
275 | h('form', |
276 | importKey, |
277 | h('button.btn', {onclick: function (e){ |
278 | if(importKey.value) { |
279 | localStorage[config.caps.shs + '/secret'] = importKey.value.replace(/\s+/g, ' ') |
280 | e.preventDefault() |
281 | alert('Your public/private key has been updated') |
282 | } |
283 | location.hash = "" |
284 | location.reload() |
285 | }}, 'Import key'), |
286 | ) |
287 | ) |
288 | ) |
289 | |
290 | screen.appendChild(hyperscroll(content)) |
291 | } |
292 | |
293 | function everythingStream () { |
294 | |
295 | var screen = document.getElementById('screen') |
296 | var content = h('div.content') |
297 | |
298 | screen.appendChild(hyperscroll(content)) |
299 | |
300 | function createStream (opts) { |
301 | return pull( |
302 | Next(sbot.query, opts, ['value', 'timestamp']), |
303 | pull.map(function (msg) { |
304 | if (msg.value) { |
305 | return render(msg) |
306 | } |
307 | }) |
308 | ) |
309 | } |
310 | |
311 | pull( |
312 | createStream({ |
313 | limit: 10, |
314 | reverse: true, |
315 | live: false, |
316 | query: [{$filter: { value: { timestamp: { $gt: 0 }}}}] |
317 | }), |
318 | stream.bottom(content) |
319 | ) |
320 | |
321 | pull( |
322 | createStream({ |
323 | limit: 10, |
324 | old: false, |
325 | live: true, |
326 | query: [{$filter: { value: { timestamp: { $gt: 0 }}}}] |
327 | }), |
328 | stream.top(content) |
329 | ) |
330 | } |
331 | |
332 | function backchannel () { |
333 | |
334 | var screen = document.getElementById('screen') |
335 | var content = h('div.content') |
336 | |
337 | screen.appendChild(hyperscroll(content)) |
338 | |
339 | var chatbox = h('input', {placeholder: 'Backchannel'}) |
340 | |
341 | var chat = h('div.content') |
342 | |
343 | var publish = h('button.btn', 'Publish', { |
344 | onclick: function () { |
345 | if (chatbox.value) { |
346 | var content = { |
347 | text: chatbox.value, |
348 | type: 'scat_message' |
349 | } |
350 | sbot.publish(content, function (err, msg) { |
351 | if (err) throw err |
352 | chatbox.value = '' |
353 | console.log('Published!', msg) |
354 | }) |
355 | } |
356 | } |
357 | }) |
358 | |
359 | chat.appendChild(h('div.message', chatbox, publish)) |
360 | |
361 | if (screen.firstChild.firstChild) { |
362 | screen.firstChild.insertBefore(chat, screen.firstChild.firstChild) |
363 | } else { |
364 | screen.firstChild.appendChild(chat) |
365 | } |
366 | |
367 | function createStream (opts) { |
368 | return pull( |
369 | Next(sbot.query, opts, ['value', 'timestamp']), |
370 | pull.map(function (msg) { |
371 | if (msg.value) { |
372 | return render(msg) |
373 | } |
374 | }) |
375 | ) |
376 | } |
377 | |
378 | pull( |
379 | createStream({ |
380 | limit: 10, |
381 | reverse: true, |
382 | live: false, |
383 | query: [{$filter: { value: { content: {type: 'scat_message'}, timestamp: { $gt: 0 }}}}] |
384 | }), |
385 | stream.bottom(content) |
386 | ) |
387 | |
388 | pull( |
389 | createStream({ |
390 | limit: 10, |
391 | old: false, |
392 | live: true, |
393 | query: [{$filter: { value: { content: {type: 'scat_message'}, timestamp: { $gt: 0 }}}}] |
394 | }), |
395 | stream.top(content) |
396 | ) |
397 | } |
398 | |
399 | |
400 | function hash () { |
401 | return window.location.hash.substring(1) |
402 | } |
403 | |
404 | module.exports = function () { |
405 | var src = hash() |
406 | |
407 | if (ref.isFeed(src)) { |
408 | userStream(src) |
409 | } else if (ref.isMsg(src)) { |
410 | msgThread(src) |
411 | } else if (src == 'mentions') { |
412 | mentionsStream() |
413 | } else if (src == 'about') { |
414 | about() |
415 | } else if (src == 'backchannel') { |
416 | backchannel() |
417 | } else if (src == 'private') { |
418 | privateStream() |
419 | } else if (src == 'key') { |
420 | keyPage() |
421 | } else { |
422 | everythingStream() |
423 | checkInvite() |
424 | } |
425 | |
426 | } |
427 |
Built with git-ssb-web