Commit d3a0c5e302f7edc7a52b5002d4c9ad4f2a2d4df3
switch to object-based routing
mix irving committed on 7/16/2017, 10:34:42 AMParent: f10b724969a4b81ac7e05057e6f753c165549cee
Files changed
app/html/app.js | changed |
app/html/search-bar.js | changed |
app/html/tabs.js | changed |
app/page/blob.js | changed |
app/page/channel.js | changed |
app/page/notifications.js | changed |
app/page/private.js | changed |
app/page/profile.js | changed |
app/page/public.js | changed |
app/page/thread.js | changed |
app/sync/addPage.js | changed |
app/sync/goTo.js | changed |
router/sync/routes.js | changed |
app/html/app.js | ||
---|---|---|
@@ -31,9 +31,13 @@ | ||
31 | 31 | window = api.app.sync.window(window) |
32 | 32 | const css = values(api.styles.css()).join('\n') |
33 | 33 | insertCss(css) |
34 | 34 | |
35 | - const initialTabs = ['/public', '/private', '/notifications'] | |
35 | + const initialTabs = [ | |
36 | + { page: 'public' }, | |
37 | + { page: 'private' }, | |
38 | + { page: 'notifications' }, | |
39 | + ] | |
36 | 40 | const tabs = api.app.html.tabs(initialTabs) |
37 | 41 | const { addPage } = api.app.sync |
38 | 42 | |
39 | 43 | const App = h('App', tabs) |
app/html/search-bar.js | ||
---|---|---|
@@ -25,11 +25,12 @@ | ||
25 | 25 | placeholder: '?search, @name, #channel', |
26 | 26 | 'ev-keyup': ev => { |
27 | 27 | switch (ev.keyCode) { |
28 | 28 | case 13: // enter |
29 | - if (goTo(input.value.trim(), !ev.ctrlKey)) { | |
30 | - input.blur() | |
31 | - } | |
29 | + var location = input.value.trim() | |
30 | + if (/^\//.test(location)) location = { page: location.replace(/^\//,'') } | |
31 | + | |
32 | + if (goTo(location, !ev.ctrlKey)) input.blur() | |
32 | 33 | return |
33 | 34 | case 27: // escape |
34 | 35 | ev.preventDefault() |
35 | 36 | input.blur() |
app/html/tabs.js | ||
---|---|---|
@@ -25,9 +25,10 @@ | ||
25 | 25 | |
26 | 26 | const search = api.app.html.searchBar() |
27 | 27 | const menu = api.app.html.menu() |
28 | 28 | const onSelect = (indexes) => { |
29 | - search.input.value = _tabs.get(indexes[0]).content.id | |
29 | + const { id, title } = _tabs.get(indexes[0]).content | |
30 | + search.input.value = title || id | |
30 | 31 | } |
31 | 32 | _tabs = Tabs(onSelect, { |
32 | 33 | append: h('div.navExtra', [ search, menu ]) |
33 | 34 | }) |
app/page/blob.js | ||
---|---|---|
@@ -8,12 +8,12 @@ | ||
8 | 8 | |
9 | 9 | exports.create = (api) => { |
10 | 10 | return nest('app.page.blob', blobPage) |
11 | 11 | |
12 | - function blobPage () { | |
13 | - return h('Blob', { id: path, title: path.slice(0, 9) + '...' }, [ | |
12 | + function blobPage ({ blob }) { | |
13 | + return h('Blob', { id: blob, title: blob.slice(0, 9) + '...' }, [ | |
14 | 14 | h('iframe', { |
15 | - src: api.blob.sync.url(path), | |
15 | + src: api.blob.sync.url(blob), | |
16 | 16 | sandbox: '' |
17 | 17 | }) |
18 | 18 | ]) |
19 | 19 | } |
app/page/channel.js | ||
---|---|---|
@@ -21,18 +21,18 @@ | ||
21 | 21 | |
22 | 22 | exports.create = function (api) { |
23 | 23 | return nest('app.page.channel', channelView) |
24 | 24 | |
25 | - function channelView (path) { | |
26 | - const channel = path.substr(1) | |
27 | - const composer = api.message.html.compose({ meta: { type: 'post', channel } }) | |
25 | + function channelView ({ channel }) { | |
26 | + const channelName = channel.substr(1) | |
27 | + const composer = api.message.html.compose({ meta: { type: 'post', channelName } }) | |
28 | 28 | const { filterMenu, filterDownThrough, filterUpThrough, resetFeed } = api.app.html.filter(draw) |
29 | 29 | const { container, content } = api.app.html.scroller({ prepend: [composer, filterMenu] }) |
30 | 30 | |
31 | 31 | function draw () { |
32 | 32 | resetFeed({ container, content }) |
33 | 33 | |
34 | - const openChannelSource = api.feed.pull.channel(channel) | |
34 | + const openChannelSource = api.feed.pull.channel(channelName) | |
35 | 35 | |
36 | 36 | pull( |
37 | 37 | openChannelSource({old: false}), |
38 | 38 | filterUpThrough(), |
@@ -46,8 +46,9 @@ | ||
46 | 46 | ) |
47 | 47 | } |
48 | 48 | draw() |
49 | 49 | |
50 | + container.id = container.title = channel | |
50 | 51 | return container |
51 | 52 | } |
52 | 53 | } |
53 | 54 |
app/page/notifications.js | ||
---|---|---|
@@ -24,9 +24,9 @@ | ||
24 | 24 | 'message.html.render': 'first' |
25 | 25 | }) |
26 | 26 | |
27 | 27 | exports.create = function (api) { |
28 | - const route = '/notifications' | |
28 | + const page = 'notifications' | |
29 | 29 | |
30 | 30 | return nest({ |
31 | 31 | 'app.html.menuItem': menuItem, |
32 | 32 | 'app.page.notifications': notificationsPage |
@@ -34,13 +34,13 @@ | ||
34 | 34 | |
35 | 35 | function menuItem () { |
36 | 36 | return h('a', { |
37 | 37 | style: { order: 3 }, |
38 | - 'ev-click': () => api.app.sync.goTo(route) | |
39 | - }, route) | |
38 | + 'ev-click': () => api.app.sync.goTo({ page }) | |
39 | + }, page) | |
40 | 40 | } |
41 | 41 | |
42 | - function notificationsPage () { | |
42 | + function notificationsPage (location) { | |
43 | 43 | const id = api.keys.sync.id() |
44 | 44 | |
45 | 45 | const { filterMenu, filterDownThrough, filterUpThrough, resetFeed } = api.app.html.filter(draw) |
46 | 46 | const { container, content } = api.app.html.scroller({ prepend: [ filterMenu ] }) |
@@ -61,8 +61,10 @@ | ||
61 | 61 | ) |
62 | 62 | } |
63 | 63 | draw() |
64 | 64 | |
65 | + container.title = page | |
66 | + container.id = JSON.stringify(location) | |
65 | 67 | return container |
66 | 68 | } |
67 | 69 | } |
68 | 70 |
app/page/private.js | ||
---|---|---|
@@ -25,9 +25,9 @@ | ||
25 | 25 | } |
26 | 26 | }) |
27 | 27 | |
28 | 28 | exports.create = function (api) { |
29 | - const route = '/private' | |
29 | + const page = 'private' | |
30 | 30 | |
31 | 31 | return nest({ |
32 | 32 | 'app.html.menuItem': menuItem, |
33 | 33 | 'app.page.private': privatePage |
@@ -35,13 +35,13 @@ | ||
35 | 35 | |
36 | 36 | function menuItem () { |
37 | 37 | return h('a', { |
38 | 38 | style: { order: 2 }, |
39 | - 'ev-click': () => api.app.sync.goTo(route) | |
40 | - }, route) | |
39 | + 'ev-click': () => api.app.sync.goTo({ page }) | |
40 | + }, page) | |
41 | 41 | } |
42 | 42 | |
43 | - function privatePage () { | |
43 | + function privatePage (location) { | |
44 | 44 | const id = api.keys.sync.id() |
45 | 45 | |
46 | 46 | const composer = api.message.html.compose({ |
47 | 47 | meta: { type: 'post' }, |
@@ -71,8 +71,10 @@ | ||
71 | 71 | ) |
72 | 72 | } |
73 | 73 | draw() |
74 | 74 | |
75 | + container.title = page | |
76 | + container.id = JSON.stringify(location) | |
75 | 77 | return container |
76 | 78 | } |
77 | 79 | } |
78 | 80 |
app/page/profile.js | ||
---|---|---|
@@ -35,9 +35,9 @@ | ||
35 | 35 | 'ev-click': () => api.app.sync.goTo(api.keys.sync.id()) |
36 | 36 | }, '/profile') |
37 | 37 | } |
38 | 38 | |
39 | - function profilePage (id) { | |
39 | + function profilePage ({ feed: id }) { | |
40 | 40 | const profile = h('Profile', [ |
41 | 41 | h('section.edit', api.about.html.edit(id)), |
42 | 42 | h('section.relationships', api.contact.html.relationships(id)), |
43 | 43 | h('section.activity', [ |
@@ -47,11 +47,8 @@ | ||
47 | 47 | ]) |
48 | 48 | |
49 | 49 | var { container, content } = api.app.html.scroller({ prepend: profile }) |
50 | 50 | |
51 | - const name = api.about.obs.name(id) | |
52 | - watch(name, function (name) { container.title = '@' + name }) | |
53 | - container.id = id | |
54 | 51 | |
55 | 52 | pull( |
56 | 53 | api.sbot.pull.userFeed({id: id, old: false, live: true}), |
57 | 54 | Scroller(container, content, api.message.html.render, true, false) |
@@ -64,8 +61,10 @@ | ||
64 | 61 | // pull.through(console.log.bind(console)), |
65 | 62 | Scroller(container, content, api.message.html.render, false, false) |
66 | 63 | ) |
67 | 64 | |
65 | + container.id = id | |
66 | + watch(api.about.obs.name(id), name => { container.title = '@' + name }) | |
68 | 67 | return container |
69 | 68 | } |
70 | 69 | } |
71 | 70 |
app/page/public.js | ||
---|---|---|
@@ -23,9 +23,9 @@ | ||
23 | 23 | } |
24 | 24 | }) |
25 | 25 | |
26 | 26 | exports.create = function (api) { |
27 | - const route = '/public' | |
27 | + const page = 'public' | |
28 | 28 | |
29 | 29 | return nest({ |
30 | 30 | 'app.html.menuItem': menuItem, |
31 | 31 | 'app.page.public': publicPage, |
@@ -33,13 +33,13 @@ | ||
33 | 33 | |
34 | 34 | function menuItem () { |
35 | 35 | return h('a', { |
36 | 36 | style: { order: 1 }, |
37 | - 'ev-click': () => api.app.sync.goTo(route) | |
38 | - }, route) | |
37 | + 'ev-click': () => api.app.sync.goTo({ page }) | |
38 | + }, page) | |
39 | 39 | } |
40 | 40 | |
41 | - function publicPage () { | |
41 | + function publicPage (location) { | |
42 | 42 | const composer = api.message.html.compose({ |
43 | 43 | meta: { type: 'post' }, |
44 | 44 | placeholder: 'Write a public message' |
45 | 45 | }) |
@@ -70,8 +70,10 @@ | ||
70 | 70 | ) |
71 | 71 | } |
72 | 72 | draw() |
73 | 73 | |
74 | + container.id = JSON.stringify(location) | |
75 | + container.title = page | |
74 | 76 | return container |
75 | 77 | } |
76 | 78 | } |
77 | 79 |
app/page/thread.js | ||
---|---|---|
@@ -26,12 +26,12 @@ | ||
26 | 26 | |
27 | 27 | exports.create = function (api) { |
28 | 28 | return nest('app.page.thread', threadPage) |
29 | 29 | |
30 | - function threadPage () { | |
30 | + function threadPage ({ msg }) { | |
31 | 31 | const myId = api.keys.sync.id() |
32 | 32 | const ImFollowing = api.contact.obs.following(myId) |
33 | - const { messages, isPrivate, rootId, lastId, channel, recps } = api.feed.obs.thread(id) | |
33 | + const { messages, isPrivate, rootId, lastId, channel, recps } = api.feed.obs.thread(msg) | |
34 | 34 | const meta = Struct({ |
35 | 35 | type: 'post', |
36 | 36 | root: rootId, |
37 | 37 | branch: lastId, |
@@ -66,14 +66,16 @@ | ||
66 | 66 | placeholder: 'Write a reply', |
67 | 67 | shrink: false |
68 | 68 | }) |
69 | 69 | const content = h('section.content', map(messages, m => { |
70 | - return api.message.html.render(resolve(m), {pageId: id}) | |
70 | + return api.message.html.render(resolve(m), {pageId: msg}) | |
71 | 71 | })) |
72 | 72 | const { container } = api.app.html.scroller({ prepend: header, content, append: composer }) |
73 | 73 | |
74 | 74 | container.classList.add('Thread') |
75 | - api.message.async.name(id, (err, name) => { | |
75 | + container.id = msg | |
76 | + container.title = msg | |
77 | + api.message.async.name(msg, (err, name) => { | |
76 | 78 | if (err) throw err |
77 | 79 | container.title = name |
78 | 80 | }) |
79 | 81 |
app/sync/addPage.js | ||
---|---|---|
@@ -12,20 +12,16 @@ | ||
12 | 12 | 'app.sync': { addPage } |
13 | 13 | }) |
14 | 14 | |
15 | 15 | // TODO : make it so error catching doesn't need this, move it into goTo |
16 | - function addPage (path, change, split) { | |
16 | + function addPage (location, change, split) { | |
17 | 17 | const tabs = api.app.html.tabs() |
18 | 18 | |
19 | - | |
20 | - // TOD (mix) : gross sheet-router hack | |
21 | - if (path[0] !== '/') path = '/'+path | |
22 | - console.log(path) | |
23 | - | |
24 | - const page = api.router.sync.router(path) | |
19 | + const page = api.router.sync.router(location) | |
25 | 20 | if (!page) return |
26 | 21 | |
27 | - page.id = page.id || path | |
22 | + // TODO - review unique page id + naming system | |
23 | + page.id = page.id || location | |
28 | 24 | tabs.add(page, change, split) |
29 | 25 | } |
30 | 26 | } |
31 | 27 |
app/sync/goTo.js | ||
---|---|---|
@@ -7,17 +7,19 @@ | ||
7 | 7 | 'app.sync.addPage': 'first' |
8 | 8 | }) |
9 | 9 | |
10 | 10 | exports.create = function (api) { |
11 | - return nest('app.sync.goTo', function goTo (path, change) { | |
11 | + return nest('app.sync.goTo', function goTo (location, change) { | |
12 | 12 | const tabs = api.app.html.tabs() |
13 | 13 | |
14 | - if (tabs.has(path)) { | |
15 | - tabs.select(path) | |
14 | + const locationSignature = JSON.stringify(location) | |
15 | + | |
16 | + if (tabs.has(locationSignature)) { | |
17 | + tabs.select(locationSignature) | |
16 | 18 | return true |
17 | 19 | } |
18 | 20 | |
19 | - api.app.sync.addPage(path, true, false) | |
21 | + api.app.sync.addPage(location, true, false) | |
20 | 22 | return change |
21 | 23 | }) |
22 | 24 | } |
23 | 25 |
router/sync/routes.js | ||
---|---|---|
@@ -1,6 +1,5 @@ | ||
1 | 1 | const nest = require('depnest') |
2 | -const { isBlob, isFeed, isMsg } = require('ssb-ref') | |
3 | 2 | |
4 | 3 | exports.gives = nest('router.sync.routes') |
5 | 4 | |
6 | 5 | exports.needs = nest({ |
@@ -25,27 +24,26 @@ | ||
25 | 24 | profile, blob, thread |
26 | 25 | } = api.app.page |
27 | 26 | |
28 | 27 | const routes = [ |
29 | - ['/', () => public()], | |
30 | - ['/errors', () => errors()], | |
31 | - ['/public', () => public()], | |
32 | - ['/private', () => private()], | |
33 | - ['/notifications', () => notifications()], | |
34 | - ['/profile', () => profile({ id: myId })], | |
35 | - ['/:key', (params) => { | |
36 | - const { key } = params | |
37 | - if (isFeed(key)) return profile(params) | |
38 | - if (isBlob(key)) return blob(params) | |
39 | - if (isMsg(key)) return thread(params) | |
40 | - if (isChannel(key)) return channel(params) | |
41 | - }] | |
28 | + [ ({ page }) => page === 'public', public ], | |
29 | + [ ({ page }) => page === 'private', private ], | |
30 | + [ ({ page }) => page === 'notifications', notifications ], | |
31 | + [ ({ page }) => page === 'errors', errors ], | |
32 | + [ ({ page }) => page === 'profile', () => profile({ id: myId }) ], | |
33 | + // TODO - use is-my-json-valid ? | |
34 | + [ ({ blob }) => isPresent(blob), blob ], | |
35 | + [ ({ channel }) => isPresent(channel), channel ], | |
36 | + [ ({ feed }) => isPresent(feed), profile ], | |
37 | + [ ({ msg }) => isPresent(msg), thread ] | |
42 | 38 | ] |
43 | 39 | |
44 | 40 | return [...sofar, ...routes] |
45 | 41 | }) |
46 | 42 | } |
47 | 43 | |
48 | -function isChannel (str) { | |
49 | - typeof str === 'string' && str[0] === '#' && str.length > 1 | |
44 | +function isPresent (content) { | |
45 | + return typeof content === 'string' && content.length > 1 | |
50 | 46 | } |
51 | 47 | |
48 | + | |
49 | + |
Built with git-ssb-web