git ssb

2+

mixmix / ticktack



Tree: ce052deca0217916e61e6c6d4ba3f7459883a09c

Files: ce052deca0217916e61e6c6d4ba3f7459883a09c / app / html / context.js

4991 bytesRaw
1const nest = require('depnest')
2const { h, computed, map, when, Dict, dictToCollection, Array: MutantArray, resolve } = require('mutant')
3const pull = require('pull-stream')
4const next = require('pull-next-step')
5const get = require('lodash/get')
6const isEmpty = require('lodash/isEmpty')
7
8exports.gives = nest('app.html.context')
9
10exports.needs = nest({
11 'about.html.image': 'first',
12 'about.obs.name': 'first',
13 'feed.pull.private': 'first',
14 'feed.pull.rollup': 'first',
15 'keys.sync.id': 'first',
16 'history.sync.push': 'first',
17 'message.html.subject': 'first',
18 'sbot.obs.localPeers': 'first',
19 'translations.sync.strings': 'first',
20})
21
22
23exports.create = (api) => {
24 return nest('app.html.context', (location) => {
25
26 const strings = api.translations.sync.strings()
27 const myKey = api.keys.sync.id()
28
29 var nearby = api.sbot.obs.localPeers()
30 var recentPeersContacted = Dict()
31 // TODO - extract as contact.obs.recentPrivate or something
32
33 pull(
34 next(api.feed.pull.private, {reverse: true, limit: 100, live: false}, ['value', 'timestamp']),
35 pull.filter(msg => msg.value.content.recps),
36 pull.drain(msg => {
37 msg.value.content.recps
38 .map(recp => typeof recp === 'object' ? recp.link : recp)
39 .filter(recp => recp != myKey)
40 .forEach(recp => {
41 if (recentPeersContacted.has(recp)) return
42
43 recentPeersContacted.put(recp, msg)
44 })
45 })
46 )
47
48 return h('Context -feed', [
49 LevelOneContext(),
50 LevelTwoContext()
51 ])
52
53 function LevelOneContext () {
54
55 return h('div.level.-one', [
56 // Nearby
57 computed(nearby, n => !isEmpty(n) ? h('header', strings.peopleNearby) : null), // TODO translate
58 map(nearby, feedId => Option({
59 notifications: Math.random() > 0.7 ? Math.floor(Math.random()*9+1) : 0, // TODO
60 imageEl: api.about.html.image(feedId), // TODO make avatar
61 label: api.about.obs.name(feedId),
62 location: computed(recentPeersContacted, recent => {
63 const lastMsg = recent[feedId]
64 return lastMsg
65 ? Object.assign(lastMsg, { feed: feedId })
66 : { page: 'threadNew', feed: feedId }
67 }),
68 selected: location.feed === feedId
69 })),
70 computed(nearby, n => !isEmpty(n) ? h('hr') : null),
71
72 // Discover
73 Option({
74 notifications: Math.floor(Math.random()*5+1),
75 imageEl: h('i.fa.fa-binoculars'),
76 label: strings.blogIndex.title,
77 location: { page: 'blogIndex' },
78 selected: ['blogIndex', 'home'].includes(location.page)
79 }),
80
81 // Recent Messages
82 map(dictToCollection(recentPeersContacted), ({ key, value }) => {
83 const feedId = key()
84 const lastMsg = value()
85 if (nearby.has(feedId)) return
86
87 return Option({
88 notifications: Math.random() > 0.7 ? Math.floor(Math.random()*9+1) : 0, // TODO
89 imageEl: api.about.html.image(feedId), // TODO make avatar
90 label: api.about.obs.name(feedId),
91 location: Object.assign(lastMsg, { feed: feedId }),
92 selected: location.feed === feedId
93 })
94 })
95 ])
96 }
97
98 function LevelTwoContext () {
99 const { key, value, feed: targetUser, page } = location
100 const root = get(value, 'content.root', key)
101 if (!targetUser) return
102
103 var threads = MutantArray()
104
105 pull(
106 next(api.feed.pull.private, {reverse: true, limit: 100, live: false}, ['value', 'timestamp']),
107 pull.filter(msg => msg.value.content.recps),
108 pull.filter(msg => msg.value.content.recps
109 .map(recp => typeof recp === 'object' ? recp.link : recp)
110 .some(recp => recp === targetUser)
111 ),
112 api.feed.pull.rollup(),
113 pull.drain(thread => threads.push(thread))
114 )
115
116 return h('div.level.-two', [
117 Option({
118 selected: page === 'threadNew',
119 location: {page: 'threadNew', feed: targetUser},
120 label: h('Button', strings.threadNew.action.new),
121 }),
122 map(threads, thread => {
123 return Option({
124 selected: thread.key === root,
125 location: Object.assign(thread, { feed: targetUser }),
126 label: api.message.html.subject(thread)
127 })
128 })
129 ])
130 }
131
132 function Option ({ notifications = 0, imageEl, label, location, selected }) {
133 const className = selected ? '-selected' : ''
134 const goToLocation = () => api.history.sync.push(resolve(location))
135
136 if (!imageEl) {
137 return h('Option', { className, 'ev-click': goToLocation }, [
138 h('div.label', label)
139 ])
140 }
141
142 return h('Option', { className }, [
143 h('div.circle', [
144 when(notifications, h('div.alert', notifications)),
145 imageEl
146 ]),
147 h('div.label', { 'ev-click': goToLocation }, label)
148 ])
149 }
150 })
151}
152
153

Built with git-ssb-web