Commit a5f729cb625d55f9a6700f99041f3adc9c2e8ffc
merged
Joran Kikke committed on 8/26/2016, 3:12:30 AMParent: f85f37c151d6d11cc3e80091cb726206fc100d4a
Parent: 3e6a0dc32fcfbe12e6fe6d56679d8bd4687ca841
Files changed
README.md | changed |
index.js | changed |
modules/app.js | changed |
modules/avatar-image.js | changed |
modules/avatar-profile.js | changed |
modules/avatar.js | changed |
modules/compose.js | changed |
modules/private.js | changed |
modules/public.js | changed |
modules/tabs.js | changed |
modules/avatar-link.js | added |
modules/network.js | added |
modules/query.js | added |
modules/theme.js | added |
modules/versions.js | added |
package.json | changed |
sbot-api.js | changed |
README.md | ||
---|---|---|
@@ -65,14 +65,15 @@ | ||
65 | 65 … | sbot plugins.install ssb-query |
66 | 66 … | sbot plugins.install ssb-ws |
67 | 67 … | # restart sbot server (go back to previous tab and kill it) |
68 | 68 … | ``` |
69 | -now clone and run patchboard. | |
69 … | +now clone and run patchbay. | |
70 | 70 … | ``` |
71 | 71 … | git clone https://github.com/dominictarr/patchbay.git |
72 | 72 … | cd patchbay |
73 | 73 … | npm install |
74 | 74 … | npm install electro electron-prebuilt -g |
75 … | +npm run build | |
75 | 76 … | electro index.js |
76 | 77 … | ``` |
77 | 78 … | |
78 | 79 … | ## modules |
@@ -85,5 +86,4 @@ | ||
85 | 86 … | |
86 | 87 … | ## License |
87 | 88 … | |
88 | 89 … | MIT |
89 | - |
index.js | ||
---|---|---|
@@ -13,8 +13,10 @@ | ||
13 | 13 … | var fs = require('fs') |
14 | 14 … | var path = require('path') |
15 | 15 … | var SbotApi = require('./sbot-api') |
16 | 16 … | |
17 … | +document.head.appendChild(h('style', require('./style.css.json'))) | |
18 … | + | |
17 | 19 … | var modules = require('./modules') |
18 | 20 … | |
19 | 21 … | var u = require('./util') |
20 | 22 … | |
@@ -35,6 +37,5 @@ | ||
35 | 37 … | document.head.appendChild( |
36 | 38 … | h('style', fs.readFileSync('./css/bootstrap_theme.css', 'utf8') |
37 | 39 … | )) |
38 | 40 … | |
39 | - | |
40 | 41 … | document.body.appendChild(modules['app.js'].app()) |
modules/app.js | ||
---|---|---|
@@ -1,11 +1,21 @@ | ||
1 | 1 … | var plugs = require('../plugs') |
2 | 2 … | var h = require('hyperscript') |
3 | 3 … | |
4 | 4 … | var screen_view = plugs.first(exports.screen_view = []) |
5 … | +var menu_items = plugs.map(exports.menu_items = []) | |
5 | 6 … | |
6 | 7 … | var status = h('div.status.error') //start off disconnected |
8 … | +var list = h('div.column', {style: 'display: none;'}) | |
7 | 9 … | |
10 … | +var menu = h('div.menu.row', list, status, { | |
11 … | + onmouseover: function (e) { | |
12 … | + list.style.display = 'flex' | |
13 … | + }, onmouseout: function () { | |
14 … | + list.style.display = 'none' | |
15 … | + } | |
16 … | +}) | |
17 … | + | |
8 | 18 … | exports.connection_status = function (err) { |
9 | 19 … | if(err) status.classList.add('error') |
10 | 20 … | else status.classList.remove('error') |
11 | 21 … | } |
@@ -16,18 +26,23 @@ | ||
16 | 26 … | } |
17 | 27 … | |
18 | 28 … | var view = screen_view(hash() || 'tabs') |
19 | 29 … | |
20 | - var screen = h('div.screen.column', status, view) | |
30 … | + var screen = h('div.screen.column', menu, view) | |
21 | 31 … | |
32 … | + menu_items().forEach(function (el) { | |
33 … | + list.appendChild(el) | |
34 … | + }) | |
35 … | + | |
22 | 36 … | window.onhashchange = function (ev) { |
23 | 37 … | var _view = view |
24 | 38 … | view = screen_view(hash() || 'tabs') |
25 | 39 … | |
26 | 40 … | if(_view) screen.replaceChild(view, _view) |
27 | 41 … | else document.body.appendChild(view) |
28 | 42 … | } |
29 | 43 … | |
44 … | + | |
30 | 45 … | return screen |
31 | 46 … | |
32 | 47 … | } |
33 | 48 … | |
@@ -49,4 +64,9 @@ | ||
49 | 64 … | |
50 | 65 … | |
51 | 66 … | |
52 | 67 … | |
68 … | + | |
69 … | + | |
70 … | + | |
71 … | + | |
72 … | + |
modules/avatar-image.js | ||
---|---|---|
@@ -26,9 +26,10 @@ | ||
26 | 26 … | |
27 | 27 … | var last = 0 |
28 | 28 … | |
29 | 29 … | //blah blah |
30 | -setTimeout(function () { | |
30 … | +exports.connection_status = function (err) { | |
31 … | + if (err) return | |
31 | 32 … | pull( |
32 | 33 … | sbot_query({ |
33 | 34 … | query: [{ |
34 | 35 … | $filter: { |
@@ -70,9 +71,9 @@ | ||
70 | 71 … | avatars[a.id] = a |
71 | 72 … | |
72 | 73 … | }) |
73 | 74 … | ) |
74 | -}) | |
75 … | +} | |
75 | 76 … | |
76 | 77 … | exports.avatar_image = function (author, classes) { |
77 | 78 … | classes = classes || '' |
78 | 79 … | if(classes && 'string' === typeof classes) classes = '.avatar--'+classes |
modules/avatar-profile.js | ||
---|---|---|
@@ -1,10 +1,9 @@ | ||
1 | 1 … | var h = require('hyperscript') |
2 | 2 … | var plugs = require('../plugs') |
3 | 3 … | var pull = require('pull-stream') |
4 | 4 … | |
5 | -var avatar_image = plugs.first(exports.avatar_image = []) | |
6 | -var avatar_name = plugs.first(exports.avatar_name = []) | |
5 … | +var avatar_image_link = plugs.first(exports.avatar_image_link = []) | |
7 | 6 … | var avatar_action = plugs.map(exports.avatar_action = []) |
8 | 7 … | var avatar_edit = plugs.first(exports.avatar_edit = []) |
9 | 8 … | |
10 | 9 … | var follows = plugs.first(exports.follows = []) |
@@ -20,9 +19,9 @@ | ||
20 | 19 … | return el |
21 | 20 … | } |
22 | 21 … | |
23 | 22 … | function image_link (id) { |
24 | - return h('a', {href:'#'+id}, avatar_image(id, 'thumbnail')) | |
23 … | + return avatar_image_link(id, 'thumbnail') | |
25 | 24 … | } |
26 | 25 … | |
27 | 26 … | exports.avatar_profile = function (id) { |
28 | 27 … | return h('div.column.profile', |
@@ -47,4 +46,8 @@ | ||
47 | 46 … | ) |
48 | 47 … | ) |
49 | 48 … | } |
50 | 49 … | |
50 … | + | |
51 … | + | |
52 … | + | |
53 … | + |
modules/avatar.js | ||
---|---|---|
@@ -1,14 +1,22 @@ | ||
1 | 1 … | var h = require('hyperscript') |
2 | 2 … | var u = require('../util') |
3 … | +var plugs = require('../plugs') | |
3 | 4 … | |
4 | - | |
5 | -var plugs = require('../plugs') | |
6 | 5 … | var avatar_name = plugs.first(exports.avatar_name = []) |
7 | 6 … | var avatar_image = plugs.first(exports.avatar_image = []) |
7 … | +var avatar_link = plugs.first(exports.avatar_link = []) | |
8 | 8 … | |
9 | 9 … | exports.avatar = function (author, classes) { |
10 | - return h('a.avatar', | |
11 | - {href:'#'+author}, | |
12 | - avatar_image(author, classes) | |
13 | - ) | |
10 … | + return exports.avatar_image_name_link(author, classes) | |
14 | 11 … | } |
12 … | + | |
13 … | +exports.avatar_image_name_link = function (author, classes) { | |
14 … | + return avatar_link(author, [ | |
15 … | + avatar_image(author, classes), | |
16 … | + avatar_name(author) | |
17 … | + ]) | |
18 … | +} | |
19 … | + | |
20 … | +exports.avatar_image_link = function (author, classes) { | |
21 … | + return avatar_link(author, avatar_image(author, classes)) | |
22 … | +} |
modules/compose.js | ||
---|---|---|
@@ -46,17 +46,26 @@ | ||
46 | 46 … | if(ev.keyCode === 13 && ev.ctrlKey) publish() |
47 | 47 … | }) |
48 | 48 … | |
49 | 49 … | var files = [] |
50 … | + var filesById = {} | |
50 | 51 … | |
51 | 52 … | function publish() { |
52 | 53 … | publishBtn.disabled = true |
53 | 54 … | var content |
54 | 55 … | try { |
55 | 56 … | content = JSON.parse(ta.value) |
56 | 57 … | } catch (err) { |
57 | 58 … | meta.text = ta.value |
58 | - meta.mentions = mentions(ta.value).concat(files) | |
59 … | + meta.mentions = mentions(ta.value).map(function (mention) { | |
60 … | + // merge markdown-detected mention with file info | |
61 … | + var file = filesById[mention.link] | |
62 … | + if (file) { | |
63 … | + if (file.type) mention.type = file.type | |
64 … | + if (file.size) mention.size = file.size | |
65 … | + } | |
66 … | + return mention | |
67 … | + }) | |
59 | 68 … | try { |
60 | 69 … | meta = prepublish(meta) |
61 | 70 … | } catch (err) { |
62 | 71 … | publishBtn.disabled = false |
@@ -84,8 +93,9 @@ | ||
84 | 93 … | //hidden until you focus the textarea |
85 | 94 … | {disabled: true}, |
86 | 95 … | file_input(function (file) { |
87 | 96 … | files.push(file) |
97 … | + filesById[file.link] = file | |
88 | 98 … | |
89 | 99 … | var embed = file.type.indexOf('image/') === 0 ? '!' : '' |
90 | 100 … | ta.value += embed + '['+file.name+']('+file.link+')' |
91 | 101 … | console.log('added:', file) |
modules/private.js | ||
---|---|---|
@@ -10,8 +10,9 @@ | ||
10 | 10 … | var message_render = plugs.first(exports.message_render = []) |
11 | 11 … | var message_compose = plugs.first(exports.message_compose = []) |
12 | 12 … | var message_unbox = plugs.first(exports.message_unbox = []) |
13 | 13 … | var sbot_log = plugs.first(exports.sbot_log = []) |
14 … | +var avatar_image_link = plugs.first(exports.avatar_image_link = []) | |
14 | 15 … | |
15 | 16 … | function unbox () { |
16 | 17 … | return pull( |
17 | 18 … | pull.filter(function (msg) { |
@@ -66,9 +67,15 @@ | ||
66 | 67 … | return div |
67 | 68 … | } |
68 | 69 … | } |
69 | 70 … | |
71 … | +function map(ary, iter) { | |
72 … | + if(Array.isArray(ary)) return ary.map(iter) | |
73 … | +} | |
74 … | + | |
70 | 75 … | exports.message_meta = function (msg) { |
71 | 76 … | if(msg.value.private) |
72 | - return h('span', 'PRIVATE') | |
77 … | + return h('span.row', 'PRIVATE', map(msg.value.content.recps, function (id) { | |
78 … | + return avatar_image_link('string' == typeof id ? id : id.link, 'thumbnail') | |
79 … | + })) | |
73 | 80 … | } |
74 | 81 … |
modules/public.js | ||
---|---|---|
@@ -8,10 +8,8 @@ | ||
8 | 8 … | var message_render = plugs.first(exports.message_render = []) |
9 | 9 … | var message_compose = plugs.first(exports.message_compose = []) |
10 | 10 … | var sbot_log = plugs.first(exports.sbot_log = []) |
11 | 11 … | |
12 | -var HighWatermark = require('pull-high-watermark') | |
13 | - | |
14 | 12 … | exports.screen_view = function (path, sbot) { |
15 | 13 … | if(path === '/public') { |
16 | 14 … | |
17 | 15 … | var content = h('div.column.scroller__content') |
@@ -29,9 +27,8 @@ | ||
29 | 27 … | ) |
30 | 28 … | |
31 | 29 … | pull( |
32 | 30 … | u.next(sbot_log, {reverse: true, limit: 100, live: false}), |
33 | -// HighWatermark(100), | |
34 | 31 … | Scroller(div, content, message_render, false, false) |
35 | 32 … | ) |
36 | 33 … | |
37 | 34 … | return div |
@@ -55,4 +52,6 @@ | ||
55 | 52 … | |
56 | 53 … | |
57 | 54 … | |
58 | 55 … | |
56 … | + | |
57 … | + |
modules/tabs.js | ||
---|---|---|
@@ -60,9 +60,9 @@ | ||
60 | 60 … | |
61 | 61 … | // tabs.select(sessionStorage.selectedTab || saved[0] || '/public') |
62 | 62 … | tabs.select('/public') |
63 | 63 … | |
64 | - tabs.onclick = function (ev) { | |
64 … | + window.onclick = function (ev) { | |
65 | 65 … | var link = ancestor(ev.target) |
66 | 66 … | if(!link) return |
67 | 67 … | var path = link.hash.substring(1) |
68 | 68 … | |
@@ -103,9 +103,9 @@ | ||
103 | 103 … | return tabs.selectedTab.scroll(-1) |
104 | 104 … | |
105 | 105 … | // close a tab |
106 | 106 … | case 88: // x |
107 | - if (tabs.selected && tabs.selected[0] !== '/') { | |
107 … | + if (tabs.selected/* && tabs.selected[0] !== '/'*/) { | |
108 | 108 … | var sel = tabs.selected |
109 | 109 … | tabs.selectRelative(-1) |
110 | 110 … | tabs.remove(sel) |
111 | 111 … | // localStorage.openTabs = JSON.stringify(tabs.tabs) |
modules/avatar-link.js | ||
---|---|---|
@@ -1,0 +1,18 @@ | ||
1 … | +var h = require('hyperscript') | |
2 … | +var plugs = require('../plugs') | |
3 … | +var avatar_name = plugs.first(exports.avatar_name = []) | |
4 … | + | |
5 … | +var signifier = require('../plugs').first(exports.signifier = []) | |
6 … | + | |
7 … | +exports.avatar_link = function (id, element) { | |
8 … | + | |
9 … | + var link = h('a.avatar', {href: "#"+id, title: id}, element) | |
10 … | + | |
11 … | + signifier(id, function (_, names) { | |
12 … | + if(names.length) | |
13 … | + link.title = names[0].name + '\n '+id | |
14 … | + }) | |
15 … | + | |
16 … | + return link | |
17 … | +} | |
18 … | + |
modules/network.js | ||
---|---|---|
@@ -1,0 +1,78 @@ | ||
1 … | +var isVisible = require('is-visible').isVisible | |
2 … | +var h = require('hyperscript') | |
3 … | +var plugs = require('../plugs') | |
4 … | + | |
5 … | +var avatar = plugs.first(exports.avatar = []) | |
6 … | +var sbot_gossip_peers = plugs.first(exports.sbot_gossip_peers = []) | |
7 … | +//sbot_gossip_connect | |
8 … | +//sbot_gossip_add | |
9 … | + | |
10 … | +var human = require('human-time') | |
11 … | + | |
12 … | +function legacyToMultiServer(addr) { | |
13 … | + return 'net:'+addr.host + ':'+addr.port + '~shs:'+addr.key.substring(1).replace('.ed25519','') | |
14 … | +} | |
15 … | + | |
16 … | +exports.menu_items = function () { | |
17 … | + return h('a', {href: '#/network'}, '/network') | |
18 … | +} | |
19 … | + | |
20 … | +exports.screen_view = function (path) { | |
21 … | + | |
22 … | + if(path !== '/network') return | |
23 … | + | |
24 … | + var ol = h('ol.network') | |
25 … | + | |
26 … | + var states = { | |
27 … | + connected: 3, | |
28 … | + connecting: 2, | |
29 … | + disconnecting: 1 | |
30 … | + } | |
31 … | + | |
32 … | + ;(function poll () { | |
33 … | + | |
34 … | + //if this tab isn't open, don't update. | |
35 … | + //todo: make a better way to do this... | |
36 … | + if(!isVisible(ol)) | |
37 … | + return setTimeout(poll, 1000) | |
38 … | + | |
39 … | + sbot_gossip_peers(function (err, list) { | |
40 … | + ol.innerHTML = '' | |
41 … | + list.sort(function (a, b) { | |
42 … | + return (states[b.state] || 0) - (states[a.state] || 0) || b.stateChange - a.stateChange | |
43 … | + }).forEach(function (peer) { | |
44 … | + ol.appendChild(h('li', | |
45 … | + avatar(peer.key, 'thumbnail'), | |
46 … | + h('div', | |
47 … | + peer.state || 'not connected', | |
48 … | + ' ', | |
49 … | + h('label', | |
50 … | + {title: new Date(peer.stateChange).toString()}, | |
51 … | + peer.stateChange && ('(' + human(new Date(peer.stateChange))) + ')') | |
52 … | + ), | |
53 … | + 'source:'+peer.source, | |
54 … | + h('pre', legacyToMultiServer(peer)) | |
55 … | + ) | |
56 … | + ) | |
57 … | + }) | |
58 … | + | |
59 … | + setTimeout(poll, 5000) | |
60 … | + }) | |
61 … | + | |
62 … | + })() | |
63 … | + | |
64 … | + return h('div.column.scroll-y', ol) | |
65 … | + | |
66 … | +} | |
67 … | + | |
68 … | + | |
69 … | + | |
70 … | + | |
71 … | + | |
72 … | + | |
73 … | + | |
74 … | + | |
75 … | + | |
76 … | + | |
77 … | + | |
78 … | + |
modules/query.js | ||
---|---|---|
@@ -1,0 +1,56 @@ | ||
1 … | +var h = require('hyperscript') | |
2 … | +var pull = require('pull-stream') | |
3 … | +var HJSON = require('hjson') | |
4 … | + | |
5 … | +var sbot_query = require('../plugs').first(exports.sbot_query = []) | |
6 … | + | |
7 … | +exports.menu_items = function () { | |
8 … | + return h('a', {href:'#/query'}, '/query') | |
9 … | +} | |
10 … | + | |
11 … | +exports.screen_view = function (path) { | |
12 … | + if(path != '/query') return | |
13 … | + var output, status, editor, stream, query | |
14 … | + | |
15 … | + function parse () { | |
16 … | + try { | |
17 … | + query = HJSON.parse(editor.value) | |
18 … | + } catch (err) { | |
19 … | + return status.textContent = err.message | |
20 … | + } | |
21 … | + status.textContent = 'okay' | |
22 … | + } | |
23 … | + | |
24 … | + return h('div.column.scroll', | |
25 … | + editor = h('textarea', {style: 'min-height:100px;', oninput: parse, onkeydown: function (e) { | |
26 … | + if(!(e.keyCode === 13 && e.ctrlKey)) return | |
27 … | + | |
28 … | + status.textContent = 'running...' | |
29 … | + parse() | |
30 … | + output.innerHTML = '' | |
31 … | + if(stream) stream.abort() | |
32 … | + | |
33 … | + console.log(query) | |
34 … | + | |
35 … | + stream = pull( | |
36 … | + sbot_query({query: query, limit: 100}), | |
37 … | + pull.drain(function (data) { | |
38 … | + output.appendChild(h('pre.query__data', | |
39 … | + JSON.stringify(data, null, 2) | |
40 … | + )) | |
41 … | + }, function (err) { | |
42 … | + if(err) status.textContent = err.stack | |
43 … | + }) | |
44 … | + ) | |
45 … | + }}), | |
46 … | + status = h('div.query__status'), | |
47 … | + output = h('div.column.query__output', {style: 'overflow-y: scroll;'}) | |
48 … | + ) | |
49 … | +} | |
50 … | + | |
51 … | + | |
52 … | + | |
53 … | + | |
54 … | + | |
55 … | + | |
56 … | + |
modules/theme.js | ||
---|---|---|
@@ -1,0 +1,143 @@ | ||
1 … | +var h = require('hyperscript') | |
2 … | +var pull = require('pull-stream') | |
3 … | +var plugs = require('../plugs') | |
4 … | +var cat = require('pull-cat') | |
5 … | + | |
6 … | +var sbot_links2 = plugs.first(exports.sbot_links2 = []) | |
7 … | +var avatar_name = plugs.first(exports.avatar_name = []) | |
8 … | +var blob_url = require('../plugs').first(exports.blob_url = []) | |
9 … | + | |
10 … | +var defaultTheme = { | |
11 … | + id: '&JFa42U6HtPm9k+s+AmpDIAoTJJI/PzoRC/J/WCfduDY=.sha256', | |
12 … | + name: 'patchbay-minimal.css' | |
13 … | +} | |
14 … | + | |
15 … | +var next = 'undefined' === typeof setImmediate ? setTimeout : setImmediate | |
16 … | + | |
17 … | +var link = document.head.appendChild(h('link', {rel: 'stylesheet'})) | |
18 … | +var activeTheme | |
19 … | + | |
20 … | +function useTheme(id) { | |
21 … | + activeTheme = id | |
22 … | + link.href = id ? blob_url(id) : '' | |
23 … | + var forms = [].slice.call(document.querySelectorAll('.themes__form')) | |
24 … | + forms.forEach(updateForm) | |
25 … | + | |
26 … | + var radios = [].slice.call(document.querySelectorAll('input[type=radio]')) | |
27 … | + radios.forEach(function (radio) { | |
28 … | + radio.checked = (radio.value === activeTheme) | |
29 … | + }) | |
30 … | +} | |
31 … | + | |
32 … | +function useSavedTheme() { | |
33 … | + useTheme(localStorage.themeId || defaultTheme.id) | |
34 … | +} | |
35 … | + | |
36 … | +next(useSavedTheme) | |
37 … | + | |
38 … | +function themes() { | |
39 … | + return cat([ | |
40 … | + pull.values([ | |
41 … | + { | |
42 … | + id: '', | |
43 … | + name: 'none', | |
44 … | + feed: '' | |
45 … | + }, | |
46 … | + defaultTheme, | |
47 … | + ]), | |
48 … | + pull( | |
49 … | + sbot_links2({ | |
50 … | + query: [ | |
51 … | + {$filter: {rel: ['mentions', {$prefix: 'patchbay-'}, {$gt: null}]}}, | |
52 … | + {$filter: {dest: {$prefix: '&'}}}, | |
53 … | + {$map: {id: 'dest', feed: 'source', name: ['rel', 1]}} | |
54 … | + ], | |
55 … | + live: true, | |
56 … | + sync: false, | |
57 … | + }), | |
58 … | + pull.filter(function (link) { | |
59 … | + return /\.css$/.test(link.name) | |
60 … | + }) | |
61 … | + ) | |
62 … | + ]) | |
63 … | +} | |
64 … | + | |
65 … | +function onRadioClick(e) { | |
66 … | + if (this.checked) useTheme(this.value) | |
67 … | +} | |
68 … | + | |
69 … | +function updateForm(form) { | |
70 … | + var same = localStorage.themeId === activeTheme | |
71 … | + form.querySelector('.themes__id').value = activeTheme | |
72 … | + form.querySelector('.themes__reset').disabled = same | |
73 … | + form.querySelector('.themes__submit').disabled = same | |
74 … | + return form | |
75 … | +} | |
76 … | + | |
77 … | +function renderTheme(link) { | |
78 … | + return h('div.theme', | |
79 … | + h('input', {type: 'radio', name: 'theme', | |
80 … | + value: link.id, onclick: onRadioClick, | |
81 … | + checked: link.id === activeTheme | |
82 … | + }), | |
83 … | + link.id ? h('a', {href: '#'+link.id}, link.name) : link.name, ' ', | |
84 … | + link.feed ? h('a', {href: '#'+link.feed}, avatar_name(link.feed)) : '' | |
85 … | + ) | |
86 … | +} | |
87 … | + | |
88 … | +function theme_view() { | |
89 … | + var themeInput | |
90 … | + var themesList = h('form.themes__list') | |
91 … | + var themesByKey = {} | |
92 … | + | |
93 … | + pull( | |
94 … | + themes(), | |
95 … | + pull.unique('id'), | |
96 … | + pull.drain(function (theme) { | |
97 … | + // replace old versions of themes in the list | |
98 … | + var key = theme.feed + theme.name | |
99 … | + var oldTheme = themesByKey[key] | |
100 … | + theme.el = renderTheme(theme) | |
101 … | + themesByKey[key] = theme | |
102 … | + if (!oldTheme) { | |
103 … | + themesList.appendChild(theme.el) | |
104 … | + } else if (oldTheme.id === localStorage.themeId | |
105 … | + || oldTheme.id === activeTheme) { | |
106 … | + // show old version because the user is still using it | |
107 … | + oldTheme.el.appendChild(document.createTextNode(' (old)')) | |
108 … | + themesList.appendChild(theme.el) | |
109 … | + } else { | |
110 … | + themesList.replaceChild(theme.el, oldTheme.el) | |
111 … | + } | |
112 … | + }, function (err) { | |
113 … | + if (err) console.error(err) | |
114 … | + }) | |
115 … | + ) | |
116 … | + | |
117 … | + return h('div.column.scroll-y', h('div', | |
118 … | + updateForm(h('form.themes__form', {onsubmit: onsubmit, onreset: onreset}, | |
119 … | + themeInput = h('input.themes__id', {placeholder: 'theme id', | |
120 … | + value: link.href}), ' ', | |
121 … | + h('input.themes__reset', {type: 'reset'}), ' ', | |
122 … | + h('input.themes__submit', {type: 'submit', value: 'Save'}))), | |
123 … | + themesList | |
124 … | + )) | |
125 … | + | |
126 … | + function onsubmit(e) { | |
127 … | + e.preventDefault() | |
128 … | + useTheme(localStorage.themeId = themeInput.value) | |
129 … | + } | |
130 … | + | |
131 … | + function onreset(e) { | |
132 … | + e.preventDefault() | |
133 … | + useSavedTheme() | |
134 … | + } | |
135 … | +} | |
136 … | + | |
137 … | +exports.menu_items = function () { | |
138 … | + return h('a', {href:'#/theme'}, '/theme') | |
139 … | +} | |
140 … | + | |
141 … | +exports.screen_view = function (path) { | |
142 … | + if(path === '/theme') return theme_view() | |
143 … | +} |
modules/versions.js | ||
---|---|---|
@@ -1,0 +1,36 @@ | ||
1 … | +var h = require('hyperscript') | |
2 … | + | |
3 … | +exports.menu_items = function () { | |
4 … | + return h('a', {href: '#/versions'}, '/versions') | |
5 … | +} | |
6 … | + | |
7 … | +exports.screen_view = function (path) { | |
8 … | + if(path !== '/versions') return | |
9 … | + | |
10 … | + if('undefined' === typeof WebBoot) | |
11 … | + return h('h1', 'must run with web-boot enabled enviroment') | |
12 … | + | |
13 … | + var content = h('div.column') | |
14 … | + | |
15 … | + WebBoot.versions(function (err, log) { | |
16 … | + log.forEach(function (e, i) { | |
17 … | + content.appendChild( | |
18 … | + h('div.row', | |
19 … | + h('a', { | |
20 … | + href: '#/run:'+e.value, | |
21 … | + onclick: function () { | |
22 … | + WebBoot.run(e.value, function () { | |
23 … | + console.log('rebooting to:', e.value) | |
24 … | + }) | |
25 … | + } | |
26 … | + }, ' ', e.value, ' ', new Date(e.ts)), | |
27 … | + !i && h('label', '(current)') | |
28 … | + ) | |
29 … | + ) | |
30 … | + }) | |
31 … | + | |
32 … | + }) | |
33 … | + | |
34 … | + return content | |
35 … | +} | |
36 … | + |
package.json | ||
---|---|---|
@@ -1,8 +1,8 @@ | ||
1 | 1 … | { |
2 | 2 … | "name": "patchbay", |
3 | 3 … | "description": "a pluggable patchwork", |
4 | - "version": "2.2.0", | |
4 … | + "version": "2.5.2", | |
5 | 5 … | "homepage": "https://github.com/dominictarr/patchbay", |
6 | 6 … | "repository": { |
7 | 7 … | "type": "git", |
8 | 8 … | "url": "git://github.com/dominictarr/patchbay.git" |
@@ -10,15 +10,17 @@ | ||
10 | 10 … | "dependencies": { |
11 | 11 … | "cont": "^1.0.3", |
12 | 12 … | "dataurl-": "^0.1.0", |
13 | 13 … | "depject": "^1.0.1", |
14 … | + "hjson": "^2.0.3", | |
14 | 15 … | "human-time": "0.0.1", |
15 | 16 … | "hypercrop": "^1.0.1", |
16 | 17 … | "hyperfile": "^1.1.0", |
17 | 18 … | "hyperlightbox": "^0.1.3", |
18 | 19 … | "hyperprogress": "0.1.0", |
19 | 20 … | "hyperscript": "^1.4.7", |
20 | 21 … | "hypertabs": "^1.2.0", |
22 … | + "is-visible": "^2.0.4", | |
21 | 23 … | "map-filter-reduce": "^3.0.1", |
22 | 24 … | "mime-types": "^2.1.11", |
23 | 25 … | "moment": "^2.13.0", |
24 | 26 … | "open-external": "^0.1.1", |
@@ -38,9 +40,9 @@ | ||
38 | 40 … | "ssb-feed": "^2.2.1", |
39 | 41 … | "ssb-keys": "^6.1.0", |
40 | 42 … | "ssb-markdown": "^3.0.0", |
41 | 43 … | "ssb-mentions": "^0.1.0", |
42 | - "ssb-sort": "0.0.0", | |
44 … | + "ssb-sort": "^1.0.0", | |
43 | 45 … | "suggest-box": "^2.2.1", |
44 | 46 … | "text-node-searcher": "^1.1.0" |
45 | 47 … | }, |
46 | 48 … | "devDependencies": { |
sbot-api.js | ||
---|---|---|
@@ -117,13 +117,16 @@ | ||
117 | 117 … | return sbot.createUserStream(opts) |
118 | 118 … | }), |
119 | 119 … | sbot_get: rec.async(function (key, cb) { |
120 | 120 … | if(CACHE[key]) cb(null, CACHE[key]) |
121 | - sbot.get(key, function (err, value) { | |
121 … | + else sbot.get(key, function (err, value) { | |
122 | 122 … | if(err) return cb(err) |
123 | 123 … | cb(null, CACHE[key] = value) |
124 | 124 … | }) |
125 | 125 … | }), |
126 … | + sbot_gossip_peers: rec.async(function (cb) { | |
127 … | + sbot.gossip.peers(cb) | |
128 … | + }), | |
126 | 129 … | sbot_publish: rec.async(function (content, cb) { |
127 | 130 … | if(content.recps) |
128 | 131 … | content = ssbKeys.box(content, content.recps.map(function (e) { |
129 | 132 … | return ref.isFeed(e) ? e : e.link |
@@ -150,4 +153,9 @@ | ||
150 | 153 … | } |
151 | 154 … | |
152 | 155 … | |
153 | 156 … | |
157 … | + | |
158 … | + | |
159 … | + | |
160 … | + | |
161 … | + |
Built with git-ssb-web