git ssb

16+

Dominic / patchbay



Commit a41e049ca3755ddfd97e7f53c9da830711e636f1

implement asyn router, make beautiful scrollTo (fixes stupid reply button)

mix irving committed on 2/8/2018, 4:53:54 AM
Parent: d5d67784390b67e685e8675d95cabae952961b35

Files changed

app/async/catch-link-click.jschanged
app/html/tabs.jschanged
app/page/thread.jschanged
app/sync/catch-keyboard-shortcut.jschanged
app/sync/goTo.jschanged
app/sync/locationId.jsadded
router/async/normalise.jschanged
router/async/router.jschanged
app/async/catch-link-click.jsView
@@ -5,9 +5,9 @@
@@ -46,9 +46,10 @@
app/html/tabs.jsView
@@ -29,8 +29,9 @@
2929
3030 try {
3131 var location = JSON.parse(id)
3232 } catch (e) {
33 + debugger
3334 throw new Error('app.html.tabs expects all page ids to be stringified location objects')
3435 }
3536
3637 api.history.sync.push(location)
app/page/thread.jsView
@@ -1,13 +1,16 @@
11 const { h, Struct, Value, when, computed, map, resolve, onceTrue } = require('mutant')
22 const nest = require('depnest')
3 +const get = require('lodash/get')
34 const { isFeed } = require('ssb-ref')
45
56 exports.gives = nest('app.page.thread')
67
78 exports.needs = nest({
89 'about.html.avatar': 'first',
910 'app.html.scroller': 'first',
11 + 'app.html.tabs': 'first',
12 + 'app.sync.locationId': 'first',
1013 'contact.obs.following': 'first',
1114 'feed.obs.thread': 'first',
1215 'keys.sync.id': 'first',
1316 'message.html.compose': 'first',
@@ -21,13 +24,15 @@
2124 exports.create = function (api) {
2225 return nest('app.page.thread', threadPage)
2326
2427 function threadPage (location) {
25- const { key } = location
28 + const root = get(location, 'value.content.root', location.key)
29 + const msg = location.key
30 + if (msg !== root) scrollDownToMessage(msg)
2631
2732 const myId = api.keys.sync.id()
2833 const ImFollowing = api.contact.obs.following(myId)
29- const { messages, isPrivate, rootId, lastId, channel, recps } = api.feed.obs.thread(key)
34 + const { messages, isPrivate, rootId, lastId, channel, recps } = api.feed.obs.thread(root)
3035 const meta = Struct({
3136 type: 'post',
3237 root: rootId,
3338 branch: lastId,
@@ -64,15 +69,15 @@
6469 placeholder: 'Write a reply',
6570 shrink: false
6671 })
6772 const content = h('section.content', map(messages, m => {
68- return api.message.html.render(resolve(m), {pageId: key})
73 + return api.message.html.render(resolve(m), {pageId: root})
6974 }))
7075 const { container } = api.app.html.scroller({ prepend: header, content, append: composer })
7176
7277 container.classList.add('Thread')
73- container.title = key
74- api.message.async.name(key, (err, name) => {
78 + container.title = msg
79 + api.message.async.name(msg, (err, name) => {
7580 if (err) throw err
7681 container.title = name
7782 })
7883
@@ -82,6 +87,26 @@
8287 channelInput.disabled = true
8388 })
8489
8590 return container
91 +
92 +
93 + function scrollDownToMessage (id) {
94 + const locationId = api.app.sync.locationId(location)
95 + const tabs = api.app.html.tabs()
96 + locateKey()
97 +
98 + function locateKey () {
99 + // wait till we're on the right page
100 + if (tabs.currentPage().id !== locationId) return setTimeout(locateKey, 200)
101 +
102 + tabs.currentPage().scroll('first')
103 + const msg = tabs.currentPage().querySelector(`[data-id='${id}']`)
104 + if (msg === null) return setTimeout(locateKey, 200)
105 +
106 + ;(msg.scrollIntoViewIfNeeded || msg.scrollIntoView).call(msg)
107 + msg.focus()
108 + }
109 + }
86110 }
87111 }
112 +
app/sync/catch-keyboard-shortcut.jsView
@@ -63,11 +63,11 @@
6363 return tabs.currentPage().scroll(1)
6464 case 75: // k = newer
6565 return tabs.currentPage().scroll(-1)
6666 case 13: // enter = open
67- return goToMessage(ev, { tabs, goTo })
67 + return goToMessage(ev, { goTo })
6868 case 79: // o = open
69- return goToMessage(ev, { tabs, goTo })
69 + return goToMessage(ev, { goTo })
7070 case 192: // ` = toggle raw message view
7171 return toggleRawMessage(ev)
7272
7373 // Tabs
@@ -99,32 +99,17 @@
9999 if (ev.shiftKey) search.activate('%', ev)
100100 }
101101 }
102102
103-function goToMessage (ev, { tabs, goTo }) {
103 +function goToMessage (ev, { goTo }) {
104104 const msg = ev.target
105105 if (!msg.classList.contains('Message')) return
106106
107- const { root, id } = msg.dataset
108- if (!root) return goTo(id)
109-
110- goTo(root)
111- setTimeout(() => scrollDownToMessage(id, tabs), 250)
107 + goTo(msg.dataset.id)
108 + // TODO - rm the dataset.root decorator
112109 }
113110
114-function scrollDownToMessage (id, tabs) {
115- tabs.currentPage().scroll('first')
116- locateKey()
117111
118- function locateKey () {
119- const msg = tabs.currentPage().querySelector(`[data-id='${id}']`)
120- if (msg === null) return setTimeout(locateKey, 100)
121-
122- ;(msg.scrollIntoViewIfNeeded || msg.scrollIntoView).call(msg)
123- msg.focus()
124- }
125-}
126-
127112 function toggleRawMessage (ev) {
128113 const msg = ev.target
129114 if (!msg.classList.contains('Message')) return
130115
app/sync/goTo.jsView
@@ -3,8 +3,9 @@
33 exports.gives = nest({ 'app.sync.goTo': true })
44
55 exports.needs = nest({
66 'app.html.tabs': 'first',
7 + 'app.sync.locationId': 'first',
78 'history.obs.store': 'first',
89 'history.sync.push': 'first',
910 'router.async.normalise': 'first',
1011 'router.async.router': 'first'
@@ -20,23 +21,28 @@
2021 // allows a refactor of catch-keyboard-shortcut + patch-inbox
2122 // - extracts scrollToMessage into app.page.thread
2223 // - router.sync.router would take (location, { position }) ?
2324
24- function goTo (location, openBackground = false, split = false) {
25- api.router.async.normalise(location, (err, location) => {
26- if (err) throw err
25 + function goTo (location, options = {}) {
26 + const {
27 + openBackground = false,
28 + split = false
29 + } = options
2730
28- const locationId = JSON.stringify(location)
31 + const tabs = api.app.html.tabs()
2932
30- const tabs = api.app.html.tabs()
33 + // currently do normalisation here only to generate normalised locationId
34 + api.router.async.normalise(location, (err, location) => {
35 + const locationId = api.app.sync.locationId(location)
36 +
3137 if (tabs.has(locationId)) {
3238 tabs.select(locationId)
3339 api.history.sync.push(location)
40 +
3441 return true
3542 }
3643
3744 api.router.async.router(location, (err, page) => {
38- debugger
3945 if (err) throw err
4046
4147 if (!page) return
4248
@@ -51,10 +57,9 @@
5157 history.set([ ..._history, location, current ])
5258 } else {
5359 api.history.sync.push(location)
5460 }
61 +
5562 })
56-
57- // return openBackground // might not be needed?
5863 })
5964 }
6065 }
app/sync/locationId.jsView
@@ -1,0 +1,20 @@
1 +const nest = require('depnest')
2 +const get = require('lodash/get')
3 +const { isMsg } = require('ssb-ref')
4 +
5 +exports.gives = nest({ 'app.sync.locationId': true })
6 +
7 +exports.create = function (api) {
8 + return nest('app.sync.locationId', locationId)
9 +
10 + function locationId (location) {
11 + if (typeof location === 'string') return string
12 +
13 + if (isMsg(location.key)) location = {
14 + key: get(location, 'value.content.root', location.key)
15 + }
16 +
17 + return JSON.stringify(location)
18 + }
19 +}
20 +
router/async/normalise.jsView
@@ -4,19 +4,24 @@
44 exports.gives = nest('router.async.normalise')
55
66 exports.needs = nest({'sbot.async.get': 'first'})
77
8-exports.create = (api) => nest('router.async.normalise', normalise)
8 +exports.create = (api) => {
9 + return nest('router.async.normalise', normalise)
910
10-function normalise (location, cb) {
11- if (typeof location === 'object') return location
11 + function normalise (location, cb) {
12 + if (typeof location === 'object') cb(null, location)
13 + else if (isMsg(location)) api.sbot.async.get(location, (err, value) => {
14 + if (err) cb(err)
15 + else cb(null, {key: location, value})
16 + })
17 + else if (isBlob(location)) cb(null, { blob: location })
18 + else if (isChannel(location)) cb(null, { channel: location })
19 + else if (isFeed(location)) cb(null, { feed: location })
20 + else if (isPage(location)) cb(null, { page: location.substring(1) })
1221
13- if (isMsg(location)) api.sbot.async.get(location, cb)
14-
15- if (isBlob(location)) cb(null, { blob: location })
16- if (isChannel(location)) cb(null, { channel: location })
17- if (isFeed(location)) cb(null, { feed: location })
18- if (isPage(location)) cb(null, { page: location.substring(1) })
22 + return true
23 + }
1924 }
2025
2126 function isChannel (str) {
2227 return typeof str === 'string' && str[0] === '#' && str.length > 1
router/async/router.jsView
@@ -17,20 +17,18 @@
1717
1818 api.router.async.normalise(location, (err, normLocation) => {
1919 if (err) return cb(err)
2020
21- debugger
22-
2321 router(normLocation, cb)
2422 })
2523
26- // return true
24 + // stop depject 'first' after this method
25 + return true
2726 })
2827 }
2928
3029 function Router (routes) {
3130 return (location, cb) => {
32- debugger
3331 const route = routes.find(([validator]) => validator(location))
3432 // signature of a route is [ routeValidator, routeFunction ]
3533
3634 if (route) cb(null, route[1](location))

Built with git-ssb-web