git ssb

16+

Dominic / patchbay



Commit abd49a5d6c84f499180e6bdbb52e5188d42df75e

Merge pull request #67 from ssbc/network_refactor

Network refactor
mix irving authored on 1/13/2017, 5:32:32 AM
GitHub committed on 1/13/2017, 5:32:32 AM
Parent: 3e3485dd605cf45a5f56a2864e4e437f7a9006c7
Parent: 2d80ace8ef63530006b28f25f53eb7577cb929c6

Files changed

h.jschanged
modules_basic/about.jschanged
modules_basic/avatar.jschanged
modules_basic/message-author.jschanged
modules_extra/network.jschanged
modules_extra/network.mcssadded
package.jsonchanged
h.jsView
@@ -1,1 +1,4 @@
1-module.exports = require('micro-css/h')(require('@mmckegg/mutant/html-element'))
1 +const { h } = require('@mmckegg/mutant')
2 +
3 +module.exports = require('micro-css/h')(h)
4 +
modules_basic/about.jsView
@@ -1,7 +1,7 @@
11 const fs = require('fs')
22 const h = require('../h')
3-const when = require('@mmckegg/mutant/when')
3 +const { when } = require('@mmckegg/mutant')
44
55 exports.needs = {
66 blob_url: 'first',
77 markdown: 'first'
modules_basic/avatar.jsView
@@ -9,29 +9,37 @@
99
1010 exports.gives = {
1111 avatar: true,
1212 avatar_image_name_link: true,
13- avatar_image_link: true
13 + avatar_image_link: true,
14 + avatar_name_link: true
1415 }
1516
1617 exports.create = function (api) {
18 + return {
19 + avatar,
20 + avatar_image_name_link,
21 + avatar_image_link,
22 + avatar_name_link
23 + }
1724
18- var exports = {}
19- exports.avatar = function (author, classes) {
25 + function avatar (author, classes) {
2026 return exports.avatar_image_name_link(author, classes)
2127 }
2228
23- exports.avatar_image_name_link = function (author, classes) {
29 + function avatar_image_name_link (author, classes) {
2430 return api.avatar_link(author, [
2531 api.avatar_image(author, classes),
2632 api.avatar_name(author)
2733 ])
2834 }
2935
30- exports.avatar_image_link = function (author, classes) {
36 + function avatar_image_link (author, classes) {
3137 return api.avatar_link(author, api.avatar_image(author, classes))
3238 }
3339
34- return exports
40 + function avatar_name_link (author, classes) {
41 + return api.avatar_link(author, api.avatar_name(author))
42 + }
3543 }
3644
3745
modules_basic/message-author.jsView
@@ -1,7 +1,7 @@
11 const fs = require('fs')
22 const h = require('../h')
3-const when = require('@mmckegg/mutant/when')
3 +const { when }= require('@mmckegg/mutant')
44
55 exports.needs = {
66 avatar_link: 'first',
77 avatar_image: 'first',
modules_extra/network.jsView
@@ -1,92 +1,84 @@
1-var isVisible = require('is-visible').isVisible
2-var h = require('hyperscript')
1 +const fs = require('fs')
2 +// const { isVisible } = require('is-visible')
3 +const h = require('../h')
4 +const human = require('human-time')
35
6 +const {
7 + Struct, Value, Dict,
8 + dictToCollection, map: mutantMap, when, computed
9 +} = require('@mmckegg/mutant')
10 +
411 //var avatar = plugs.first(exports.avatar = [])
512 //var sbot_gossip_peers = plugs.first(exports.sbot_gossip_peers = [])
613 //var sbot_gossip_connect = plugs.first(exports.sbot_gossip_connect = [])
714
815 exports.needs = {
9- avatar: 'first',
16 + avatar_image_link: 'first',
17 + avatar_name_link: 'first',
1018 sbot_gossip_peers: 'first',
1119 sbot_gossip_connect: 'first'
1220 }
1321
1422 exports.gives = {
1523 menu_items: true,
1624 builtin_tabs: true,
17- screen_view: true
25 + screen_view: true,
26 + mcss: true
1827 }
1928
2029 //sbot_gossip_connect
2130 //sbot_gossip_add
2231
23-var human = require('human-time')
2432
2533 function legacyToMultiServer(addr) {
2634 return 'net:'+addr.host + ':'+addr.port + '~shs:'+addr.key.substring(1).replace('.ed25519','')
2735 }
2836
29-//types of peers
30-
31-
3237 //on the same wifi network
33-function isLocal (e) {
38 +function isLocal (peer) {
3439 // don't rely on private ip address, because
3540 // cjdns creates fake private ip addresses.
36- return ip.isPrivate(e.host) && e.type === 'local'
41 + return ip.isPrivate(peer.host) && peer.type === 'local'
3742 }
3843
3944
40-//pub is running scuttlebot >=8
41-//have connected successfully.
42-function isLongterm (e) {
43- return e.ping && e.ping.rtt && e.ping.rtt.mean > 0
44-}
45 +function getType (peer) {
46 + return (
47 + isLongterm(peer) ? 'modern'
48 + : isLegacy(peer) ? 'legacy'
49 + : isInactive(peer) ? 'inactive'
50 + : isUnattempted(peer) ? 'unattempted'
51 + : 'other' //should never happen
52 + )
4553
46-//pub is running scuttlebot < 8
47-//have connected sucessfully
48-function isLegacy (peer) {
49- return /connect/.test(peer.state) || (peer.duration && peer.duration.mean) > 0 && !isLongterm(peer)
50-}
54 + //pub is running scuttlebot >=8
55 + //have connected successfully.
56 + function isLongterm (peer) {
57 + return peer.ping && peer.ping.rtt && peer.ping.rtt.mean > 0
58 + }
5159
52-//tried to connect, but failed.
53-function isInactive (e) {
54- return e.stateChange && (e.duration && e.duration.mean == 0)
55-}
60 + //pub is running scuttlebot < 8
61 + //have connected sucessfully
62 + function isLegacy (peer) {
63 + return /connect/.test(peer.state) || (peer.duration && peer.duration.mean) > 0 && !isLongterm(peer)
64 + }
5665
57-//havn't tried to connect peer yet.
58-function isUnattempted (e) {
59- return !e.stateChange
60-}
66 + //tried to connect, but failed.
67 + function isInactive (peer) {
68 + return peer.stateChange && (peer.duration && peer.duration.mean == 0)
69 + }
6170
62-function getType (e) {
63- return (
64- isLongterm(e) ? 'modern'
65- : isLegacy(e) ? 'legacy'
66- : isInactive(e) ? 'inactive'
67- : isUnattempted(e) ? 'unattempted'
68- : 'other' //should never happen
69- )
71 + //havn't tried to connect peer yet.
72 + function isUnattempted (peer) {
73 + return !peer.stateChange
74 + }
7075 }
7176
72-function origin (e) {
73- return e.source === 'local' ? 0 : 1
77 +function origin (peer) {
78 + return peer.source === 'local' ? 0 : 1
7479 }
7580
76-var states = {
77- connected: 3,
78- connecting: 2
79-}
80-
81-var types = {
82- modern: 4,
83- legacy: 3,
84- inactive: 2,
85- unattempted: 1,
86- other: 0
87-}
88-
8981 function round(n) {
9082 return Math.round(n*100)/100
9183 }
9284
@@ -99,78 +91,163 @@
9991 else
10092 return round(s)+'ms'
10193 }
10294
95 +function peerListSort (a, b) {
96 + var states = {
97 + connected: 3,
98 + connecting: 2
99 + }
103100
101 + //types of peers
102 + var types = {
103 + modern: 4,
104 + legacy: 3,
105 + inactive: 2,
106 + unattempted: 1,
107 + other: 0
108 + }
104109
105-exports.create = function (api) {
110 + return (
111 + (states[b.state] || 0) - (states[a.state] || 0)
112 + || origin(b) - origin(a)
113 + || types[getType(b)] - types[getType(a)]
114 + || b.stateChange - a.stateChange
115 + )
116 +}
106117
107- return {
108- menu_items: function () {
109- return h('a', {href: '#/network'}, '/network')
110- },
118 +function formatDate (time) {
119 + return new Date(time).toString()
120 +}
111121
112- builtin_tabs: function () {
113- return ['/network']
114- },
122 +function humanDate (time) {
123 + return human(new Date(time)).replace(/minute/, 'min').replace(/second/, 'sec')
124 +}
115125
116- screen_view: function (path) {
126 +exports.create = function (api) {
117127
118- if(path !== '/network') return
128 + return {
129 + menu_items: () => h('a', {href: '#/network'}, '/network'),
130 + builtin_tabs: () => ['/network'],
131 + screen_view,
132 + mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
133 + }
119134
120- var ol = h('ul.network')
135 + function screen_view (path) {
136 + if (path !== '/network') return
121137
122- ;(function poll () {
138 + var peers = obs_gossip_peers(api)
123139
124- //if this tab isn't open, don't update.
125- //todo: make a better way to do this...
126- if(!isVisible(ol))
127- return setTimeout(poll, 1000)
140 + return h('div', { style: {'overflow':'auto'}, className: 'column scroller' }, [
141 + h('Network', [
142 + mutantMap(peers, peer => {
143 + var { key, ping, source, state, stateChange } = peer
128144
129- api.sbot_gossip_peers(function (err, list) {
130- ol.innerHTML = ''
131- list.sort(function (a, b) {
132- return (
133- (states[b.state] || 0) - (states[a.state] || 0)
134- || origin(b) - origin(a)
135- || types[getType(b)] - types[getType(a)]
136- || b.stateChange - a.stateChange
137- )
138- }).forEach(function (peer) {
139- ol.appendChild(h('div',
140- api.avatar(peer.key, 'thumbnail'),
141- h('div',
142- peer.state || 'not connected',
143- ' ',
144- getType(peer),
145- ' ',
146- //TODO: show nicer details, with labels. etc.
147- (peer.ping && peer.ping.rtt) ? duration(peer.ping.rtt.mean) : '',
148- ' ',
149- (peer.ping && peer.ping.skew) ? duration(peer.ping.skew.mean) : '',
150- h('label',
151- {title: new Date(peer.stateChange).toString()},
152- peer.stateChange && ('(' + human(new Date(peer.stateChange))) + ')')
153- ),
154- 'source:'+peer.source,
155- h('pre', legacyToMultiServer(peer)),
156- h('button', 'connect', {onclick: function () {
157- api.sbot_gossip_connect(peer, function (err) {
145 + return h('NetworkConnection', [
146 + h('section.avatar', [
147 + api.avatar_image_link(key()),
148 + ]),
149 + h('section.name', [
150 + api.avatar_name_link(key()),
151 + ]),
152 + h('section.type', [
153 + computed(peer, getType),
154 + ]),
155 + h('section.source', [
156 + h('label', 'source:'),
157 + h('code', source)
158 + ]),
159 + h('section.state', [
160 + h('label', 'state:'),
161 + h('i', {
162 + className: computed(state, (state) => '-'+state)
163 + }),
164 + h('code', when(state, state, 'not connected'))
165 + ]),
166 + h('section.actions', [
167 + h('button', {
168 + 'ev-click': () => {
169 + api.sbot_gossip_connect(peer(), (err) => {
158170 if(err) console.error(err)
159- else console.log('connected to', peer)
171 + else console.log('connected to', peer())
160172 })
161- }})
173 + }},
174 + 'connect'
162175 )
163- )
164- })
165-
166- setTimeout(poll, 5000)
176 + ]),
177 + h('section.time-ago', [
178 + h('div',
179 + { title: computed(stateChange, formatDate) },
180 + [ computed(stateChange, humanDate) ]
181 + )
182 + ]),
183 + h('section.ping', [
184 + h('div.rtt', [
185 + h('label', 'rtt:'),
186 + h('code', computed(ping.rtt.mean, duration))
187 + ]),
188 + h('div.skew', [
189 + h('label', 'skew:'),
190 + h('code', computed(ping.skew.mean, duration))
191 + ]),
192 + ]),
193 + h('section.address', [
194 + h('code', computed(peer, legacyToMultiServer))
195 + ])
196 + ])
167197 })
198 + ])
199 + ])
200 + }
201 +}
168202
169- })()
203 +function obs_gossip_peers (api) {
204 + var timer = null
205 + var state = Dict({}, {
206 + onListen: () => {
207 + timer = setInterval(refresh, 5e3)
208 + },
209 + onUnlisten: () => {
210 + clearInterval(timer)
211 + }
212 + })
170213
171- return h('div.column.scroll-y', ol)
172- }
214 + refresh()
215 +
216 + return dictToCollection.values(state)
217 +
218 + function refresh () {
219 + api.sbot_gossip_peers((err, peers) => {
220 + peers.forEach(data => {
221 + var id = legacyToMultiServer(data)
222 + var current = state.get(id)
223 + if (!current) {
224 + current = Peer()
225 + current.set(data)
226 + state.put(id, current)
227 + } else {
228 + current.set(data)
229 + }
230 + })
231 + })
173232 }
174233 }
175234
235 +function Peer () {
236 + var peer = Struct({
237 + key: Value(),
238 + ping: Struct({
239 + rtt: Struct({
240 + mean: Value()
241 + }),
242 + skew: Struct({
243 + mean: Value()
244 + })
245 + }),
246 + source: Value(),
247 + state: Value(),
248 + stateChange: Value()
249 + })
176250
251 + return peer
252 +}
253 +
modules_extra/network.mcssView
@@ -1,0 +1,117 @@
1 +Network {
2 + div {
3 + margin: .8rem
4 + border-bottom: 1px solid gainsboro
5 + }
6 +
7 +}
8 +
9 +NetworkConnection {
10 + padding-left: 6rem
11 + padding-bottom: .8rem
12 + position: relative
13 +
14 + display: flex
15 + flex-direction: row
16 + flex-wrap: wrap
17 + align-items: center
18 +
19 + section.avatar {
20 + position: absolute
21 + left: 0
22 + top: 0
23 +
24 + a img {
25 + height: 3rem
26 + width: 3rem
27 + }
28 + }
29 +
30 + section.time-ago {
31 + position: absolute
32 + left: 0
33 + top: 3.5rem
34 +
35 + font-size: .8rem
36 + $textSubtle
37 + }
38 +
39 + section.name {
40 + flex-basis: 100%
41 +
42 + margin-right: 1rem
43 + }
44 +
45 + section.type {
46 + flex-basis: 100%
47 +
48 + font-size: .8rem
49 + $textSubtle
50 + }
51 +
52 + section.source {
53 + flex-basis: 100%
54 + label { margin-right: .5rem }
55 + }
56 +
57 + section.state {
58 + display: flex
59 + flex-direction: row
60 + align-items: center
61 +
62 + margin-right: 2rem
63 +
64 + label { margin-right: .5rem }
65 + i {
66 + width: 1rem
67 + height: 1rem
68 + border-radius: .5rem
69 +
70 + margin: 0 .2rem 0 .5rem
71 +
72 + background: #ccc
73 +
74 + -connecting, -disconnecting {
75 + background: #95cc95
76 + }
77 +
78 + -connected {
79 + background: #06e206
80 + }
81 + }
82 + }
83 +
84 + section.actions {
85 + button {
86 + padding: .2rem
87 + font-size: .7rem
88 + }
89 + }
90 +
91 +
92 + section.ping {
93 + flex-basis: 100%
94 + display: flex
95 +
96 + font-size: .8rem
97 + $textSubtle
98 +
99 + div.rtt {
100 + flex-basis: 8rem
101 + label { margin-right: .5rem }
102 + }
103 +
104 + div.skew {
105 + flex-basis: 8rem
106 + label { margin-right: .5rem }
107 + }
108 + }
109 +
110 + section.address{
111 + flex-basis: 100%
112 +
113 + font-size: .8rem
114 + $textSubtle
115 + }
116 +}
117 +
package.jsonView
@@ -7,9 +7,9 @@
77 "type": "git",
88 "url": "git://github.com/dominictarr/patchbay.git"
99 },
1010 "dependencies": {
11- "@mmckegg/mutant": "^3.10.1",
11 + "@mmckegg/mutant": "^3.12.0",
1212 "brfs": "^1.4.3",
1313 "cont": "^1.0.3",
1414 "dataurl-": "^0.1.0",
1515 "depject": "^3.0.0",

Built with git-ssb-web