Commit 9510d7867738dfa7a4aaee17c183c86bb081f55e
object-based routing iterated
mix irving committed on 7/19/2017, 9:19:50 AMParent: d3a0c5e302f7edc7a52b5002d4c9ad4f2a2d4df3
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/errors.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/goTo.js | changed |
router/sync/routes.js | changed |
app/html/app.js | ||
---|---|---|
@@ -31,13 +31,10 @@ | ||
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 = [ | |
36 | - { page: 'public' }, | |
37 | - { page: 'private' }, | |
38 | - { page: 'notifications' }, | |
39 | - ] | |
35 | + const initialTabs = [ '/public', '/private', '/notifications' ] | |
36 | + // NB router converts these to { page: '/public' } | |
40 | 37 | const tabs = api.app.html.tabs(initialTabs) |
41 | 38 | const { addPage } = api.app.sync |
42 | 39 | |
43 | 40 | const App = h('App', tabs) |
app/html/search-bar.js | ||
---|---|---|
@@ -26,10 +26,8 @@ | ||
26 | 26 | 'ev-keyup': ev => { |
27 | 27 | switch (ev.keyCode) { |
28 | 28 | case 13: // enter |
29 | 29 | var location = input.value.trim() |
30 | - if (/^\//.test(location)) location = { page: location.replace(/^\//,'') } | |
31 | - | |
32 | 30 | if (goTo(location, !ev.ctrlKey)) input.blur() |
33 | 31 | return |
34 | 32 | case 27: // escape |
35 | 33 | ev.preventDefault() |
app/html/tabs.js | ||
---|---|---|
@@ -25,10 +25,21 @@ | ||
25 | 25 | |
26 | 26 | const search = api.app.html.searchBar() |
27 | 27 | const menu = api.app.html.menu() |
28 | 28 | const onSelect = (indexes) => { |
29 | - const { id, title } = _tabs.get(indexes[0]).content | |
30 | - search.input.value = title || id | |
29 | + const { id } = _tabs.get(indexes[0]).content | |
30 | + | |
31 | + try { | |
32 | + const location = JSON.parse(id) | |
33 | + var locationForSearchBar = Object.keys(location) | |
34 | + .map(k => location[k]) | |
35 | + .join(' + ') | |
36 | + } | |
37 | + catch (e) { | |
38 | + throw new Error('app/html/tabs expects all page ids to be stringified location objects') | |
39 | + var locationForSearchBar = id | |
40 | + } | |
41 | + search.input.value = locationForSearchBar | |
31 | 42 | } |
32 | 43 | _tabs = Tabs(onSelect, { |
33 | 44 | append: h('div.navExtra', [ search, menu ]) |
34 | 45 | }) |
app/page/blob.js | ||
---|---|---|
@@ -8,10 +8,11 @@ | ||
8 | 8 | |
9 | 9 | exports.create = (api) => { |
10 | 10 | return nest('app.page.blob', blobPage) |
11 | 11 | |
12 | - function blobPage ({ blob }) { | |
13 | - return h('Blob', { id: blob, title: blob.slice(0, 9) + '...' }, [ | |
12 | + function blobPage (location) { | |
13 | + const { blob } = location | |
14 | + return h('Blob', { id: JSON.stringify(location), title: blob.slice(0, 9) + '...' }, [ | |
14 | 15 | h('iframe', { |
15 | 16 | src: api.blob.sync.url(blob), |
16 | 17 | sandbox: '' |
17 | 18 | }) |
app/page/channel.js | ||
---|---|---|
@@ -21,9 +21,10 @@ | ||
21 | 21 | |
22 | 22 | exports.create = function (api) { |
23 | 23 | return nest('app.page.channel', channelView) |
24 | 24 | |
25 | - function channelView ({ channel }) { | |
25 | + function channelView (location) { | |
26 | + const { channel } = location | |
26 | 27 | const channelName = channel.substr(1) |
27 | 28 | const composer = api.message.html.compose({ meta: { type: 'post', channelName } }) |
28 | 29 | const { filterMenu, filterDownThrough, filterUpThrough, resetFeed } = api.app.html.filter(draw) |
29 | 30 | const { container, content } = api.app.html.scroller({ prepend: [composer, filterMenu] }) |
@@ -46,9 +47,10 @@ | ||
46 | 47 | ) |
47 | 48 | } |
48 | 49 | draw() |
49 | 50 | |
50 | - container.id = container.title = channel | |
51 | + container.id = JSON.stringify(location) | |
52 | + container.title = channel | |
51 | 53 | return container |
52 | 54 | } |
53 | 55 | } |
54 | 56 |
app/page/errors.js | ||
---|---|---|
@@ -8,12 +8,12 @@ | ||
8 | 8 | |
9 | 9 | exports.create = function (api) { |
10 | 10 | return nest('app.page.errors', errorsPage) |
11 | 11 | |
12 | - function errorsPage () { | |
12 | + function errorsPage (location) { | |
13 | 13 | var { container, content } = api.app.html.scroller() |
14 | 14 | |
15 | - container.id = '/errors' | |
15 | + container.id = JSON.stringify(location) | |
16 | 16 | container.classList = ['-errors'] |
17 | 17 | |
18 | 18 | // add a dummy entry in the list |
19 | 19 |
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 page = 'notifications' | |
28 | + const page = '/notifications' | |
29 | 29 | |
30 | 30 | return nest({ |
31 | 31 | 'app.html.menuItem': menuItem, |
32 | 32 | 'app.page.notifications': notificationsPage |
app/page/private.js | ||
---|---|---|
@@ -25,9 +25,9 @@ | ||
25 | 25 | } |
26 | 26 | }) |
27 | 27 | |
28 | 28 | exports.create = function (api) { |
29 | - const page = 'private' | |
29 | + const page = '/private' | |
30 | 30 | |
31 | 31 | return nest({ |
32 | 32 | 'app.html.menuItem': menuItem, |
33 | 33 | 'app.page.private': privatePage |
app/page/profile.js | ||
---|---|---|
@@ -35,9 +35,10 @@ | ||
35 | 35 | 'ev-click': () => api.app.sync.goTo(api.keys.sync.id()) |
36 | 36 | }, '/profile') |
37 | 37 | } |
38 | 38 | |
39 | - function profilePage ({ feed: id }) { | |
39 | + function profilePage (location) { | |
40 | + const { feed: id } = location | |
40 | 41 | const profile = h('Profile', [ |
41 | 42 | h('section.edit', api.about.html.edit(id)), |
42 | 43 | h('section.relationships', api.contact.html.relationships(id)), |
43 | 44 | h('section.activity', [ |
@@ -61,9 +62,9 @@ | ||
61 | 62 | // pull.through(console.log.bind(console)), |
62 | 63 | Scroller(container, content, api.message.html.render, false, false) |
63 | 64 | ) |
64 | 65 | |
65 | - container.id = id | |
66 | + container.id = JSON.stringify(location) | |
66 | 67 | watch(api.about.obs.name(id), name => { container.title = '@' + name }) |
67 | 68 | return container |
68 | 69 | } |
69 | 70 | } |
app/page/public.js | ||
---|---|---|
@@ -23,9 +23,9 @@ | ||
23 | 23 | } |
24 | 24 | }) |
25 | 25 | |
26 | 26 | exports.create = function (api) { |
27 | - const page = 'public' | |
27 | + const page = '/public' | |
28 | 28 | |
29 | 29 | return nest({ |
30 | 30 | 'app.html.menuItem': menuItem, |
31 | 31 | 'app.page.public': publicPage, |
app/page/thread.js | ||
---|---|---|
@@ -26,9 +26,10 @@ | ||
26 | 26 | |
27 | 27 | exports.create = function (api) { |
28 | 28 | return nest('app.page.thread', threadPage) |
29 | 29 | |
30 | - function threadPage ({ msg }) { | |
30 | + function threadPage (location) { | |
31 | + const { msg } = location | |
31 | 32 | const myId = api.keys.sync.id() |
32 | 33 | const ImFollowing = api.contact.obs.following(myId) |
33 | 34 | const { messages, isPrivate, rootId, lastId, channel, recps } = api.feed.obs.thread(msg) |
34 | 35 | const meta = Struct({ |
@@ -71,9 +72,9 @@ | ||
71 | 72 | })) |
72 | 73 | const { container } = api.app.html.scroller({ prepend: header, content, append: composer }) |
73 | 74 | |
74 | 75 | container.classList.add('Thread') |
75 | - container.id = msg | |
76 | + container.id = JSON.stringify(location) | |
76 | 77 | container.title = msg |
77 | 78 | api.message.async.name(msg, (err, name) => { |
78 | 79 | if (err) throw err |
79 | 80 | container.title = name |
app/sync/goTo.js | ||
---|---|---|
@@ -3,19 +3,21 @@ | ||
3 | 3 | exports.gives = nest({ 'app.sync.goTo': true }) |
4 | 4 | |
5 | 5 | exports.needs = nest({ |
6 | 6 | 'app.html.tabs': 'first', |
7 | - 'app.sync.addPage': 'first' | |
7 | + 'app.sync.addPage': 'first', | |
8 | + 'router.sync.normalise': 'first' | |
8 | 9 | }) |
9 | 10 | |
10 | 11 | exports.create = function (api) { |
11 | 12 | return nest('app.sync.goTo', function goTo (location, change) { |
12 | 13 | const tabs = api.app.html.tabs() |
13 | 14 | |
14 | - const locationSignature = JSON.stringify(location) | |
15 | + location = api.router.sync.normalise(location) | |
16 | + const locationId = JSON.stringify(location) | |
15 | 17 | |
16 | - if (tabs.has(locationSignature)) { | |
17 | - tabs.select(locationSignature) | |
18 | + if (tabs.has(locationId)) { | |
19 | + tabs.select(locationId) | |
18 | 20 | return true |
19 | 21 | } |
20 | 22 | |
21 | 23 | api.app.sync.addPage(location, true, false) |
router/sync/routes.js | ||
---|---|---|
@@ -24,13 +24,13 @@ | ||
24 | 24 | profile, blob, thread |
25 | 25 | } = api.app.page |
26 | 26 | |
27 | 27 | const routes = [ |
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 }) ], | |
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 | 33 | // TODO - use is-my-json-valid ? |
34 | 34 | [ ({ blob }) => isPresent(blob), blob ], |
35 | 35 | [ ({ channel }) => isPresent(channel), channel ], |
36 | 36 | [ ({ feed }) => isPresent(feed), profile ], |
Built with git-ssb-web