git ssb

16+

Dominic / patchbay



Commit dab8336e2c9b7ae4d3e407ce7c8059bea3f4e566

ideal layout for nested message modules

mix irving committed on 1/16/2017, 5:53:25 AM
Parent: f93ceefd06a4ef69e3af1d2fb39bc0fed84c2c7a

Files changed

modules_basic/index.jschanged
modules_basic/message-author.jsdeleted
modules_basic/message/author.jsadded
modules_basic/message/author.mcssadded
modules_basic/message/backlinks.jsadded
modules_basic/message/backlinks.mcssadded
modules_basic/message/link.jsadded
modules_basic/message/name.jsadded
modules_basic/message/render.jsadded
modules_basic/message/render.mcssadded
modules_basic/message-author.mcssdeleted
modules_basic/message-backlinks.jsdeleted
modules_basic/message-backlinks.mcssdeleted
modules_basic/message-link.jsdeleted
modules_basic/message-name.jsdeleted
modules_basic/message.jsdeleted
modules_basic/message.mcssdeleted
modules_basic/index.jsView
@@ -11,13 +11,15 @@
1111 "follow.js": require('./follow.js'),
1212 "invite.js": require('./invite.js'),
1313 "like.js": require('./like.js'),
1414 "markdown.js": require('./markdown.js'),
15- "message-author.js": require('./message-author.js'),
16- "message-backlinks.js": require('./message-backlinks.js'),
17- "message-link.js": require('./message-link.js'),
18- "message-name.js": require('./message-name.js'),
19- "message.js": require('./message.js'),
15 + message: {
16 + author: require('./message/author.js'),
17 + backlinks: require('./message/backlinks.js'),
18 + link: require('./message/link.js'),
19 + name: require('./message/name.js'),
20 + render: require('./message/render.js'),
21 + },
2022 "names.js": require('./names.js'),
2123 "post.js": require('./post.js'),
2224 "private.js": require('./private.js'),
2325 "pub.js": require('./pub.js'),
modules_basic/message-author.jsView
@@ -1,39 +1,0 @@
1-const fs = require('fs')
2-const h = require('../h')
3-const { when }= require('@mmckegg/mutant')
4-
5-exports.needs = {
6- avatar_link: 'first',
7- avatar_image: 'first',
8- avatar_name: 'first',
9- timestamp: 'first'
10-}
11-
12-exports.gives = {
13- message_author: true,
14- mcss: true
15-}
16-
17-exports.create = function (api) {
18- return {
19- message_author,
20- mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
21- }
22-
23- function message_author (msg, opts = {}) {
24- var { size = 'small' } = opts
25- var { value } = msg
26- var { author } = value
27-
28- return h('MessageAuthor', {
29- className: `-${size}`
30- }, [
31- when(size !== 'mini',
32- h('section -image', api.avatar_link(author, api.avatar_image(author, 'thumbnail')))
33- ),
34- h('section -name', api.avatar_link(author, api.avatar_name(author))),
35- h('section -timestamp', api.timestamp(msg))
36- ])
37- }
38-}
39-
modules_basic/message/author.jsView
@@ -1,0 +1,39 @@
1 +const fs = require('fs')
2 +const h = require('../../h')
3 +const { when }= require('@mmckegg/mutant')
4 +
5 +exports.needs = {
6 + avatar_link: 'first',
7 + avatar_image: 'first',
8 + avatar_name: 'first',
9 + timestamp: 'first'
10 +}
11 +
12 +exports.gives = {
13 + author: true,
14 + mcss: true
15 +}
16 +
17 +exports.create = function (api) {
18 + return {
19 + author,
20 + mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
21 + }
22 +
23 + function author (msg, opts = {}) {
24 + var { size = 'small' } = opts
25 + var { value } = msg
26 + var { author } = value
27 +
28 + return h('MessageAuthor', {
29 + className: `-${size}`
30 + }, [
31 + when(size !== 'mini',
32 + h('section -image', api.avatar_link(author, api.avatar_image(author, 'thumbnail')))
33 + ),
34 + h('section -name', api.avatar_link(author, api.avatar_name(author))),
35 + h('section -timestamp', api.timestamp(msg))
36 + ])
37 + }
38 +}
39 +
modules_basic/message/author.mcssView
@@ -1,0 +1,38 @@
1 +MessageAuthor {
2 + display: flex
3 + flex-direction: column
4 +
5 + section {
6 + -image {
7 + margin-bottom: .3rem
8 + }
9 +
10 + -name {
11 + max-width: 7rem
12 + a { $textPrimary }
13 + }
14 +
15 + -timestamp {
16 +
17 + }
18 + }
19 +
20 + -mini {
21 + flex-direction: row
22 +
23 + section {
24 + margin-right: .5rem
25 +
26 + -name {
27 + position: initial
28 + left: initial
29 + min-width: 6.5rem
30 + max-width: none
31 + }
32 +
33 + -timestamp {
34 +
35 + }
36 + }
37 + }
38 +}
modules_basic/message/backlinks.jsView
@@ -1,0 +1,48 @@
1 +const fs = require('fs')
2 +const h = require('../../h')
3 +
4 +exports.needs = {
5 + message_name: 'first'
6 +}
7 +
8 +exports.gives = {
9 + backlinks: true,
10 + mcss: true
11 +}
12 +
13 +exports.create = function (api) {
14 + return {
15 + backlinks,
16 + mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
17 + }
18 +
19 + function backlinks (msg) {
20 + var links = []
21 + for(var k in CACHE) {
22 + var _msg = CACHE[k]
23 + var mentions = _msg.content.mentions
24 +
25 + if(Array.isArray(mentions)) {
26 + for(var i = 0; i < mentions.length; i++)
27 + if(mentions[i].link == msg.key)
28 + links.push(k)
29 + }
30 + }
31 +
32 + if (links.length === 0) return null
33 +
34 + var hrefList = h('ul')
35 + links.forEach(link => {
36 + api.message_name(link, (err, name) => {
37 + if (err) throw err
38 + hrefList.appendChild(h('li',
39 + h('a -backlink', { href: `#${link}` }, name)
40 + ))
41 + })
42 + })
43 + return h('MessageBacklinks', [
44 + h('header', 'backlinks:'),
45 + hrefList
46 + ])
47 + }
48 +}
modules_basic/message/backlinks.mcssView
@@ -1,0 +1,21 @@
1 +MessageBacklinks {
2 + font-size: .9rem
3 + margin-top: .5rem
4 +
5 + header {
6 + $textSubtle
7 + }
8 +
9 + ul {
10 + padding-left: 1rem
11 +
12 + li {
13 + a {
14 + -backlink {
15 + $textSubtle
16 +
17 + }
18 + }
19 + }
20 + }
21 +}
modules_basic/message/link.jsView
@@ -1,0 +1,39 @@
1 +var h = require('hyperscript')
2 +var ref = require('ssb-ref')
3 +
4 +//var first = require('../plugs').first
5 +//var sbot_get = first(exports.sbot_get = [])
6 +//var message_name = first(exports.message_name = [])
7 +
8 +exports.needs = {
9 + message_name: 'first'
10 +}
11 +
12 +exports.gives = 'link'
13 +
14 +exports.create = function (api) {
15 +
16 + return function (id) {
17 +
18 + if('string' !== typeof id)
19 + throw new Error('link must be to message id')
20 +
21 + var link = h('a', {href: '#'+id}, id.substring(0, 10)+'...')
22 +
23 + if(ref.isMsg(id))
24 + api.message_name(id, function (err, name) {
25 + if(err) console.error(err)
26 + else link.textContent = name
27 + })
28 +
29 + return link
30 + }
31 +}
32 +
33 +
34 +
35 +
36 +
37 +
38 +
39 +
modules_basic/message/name.jsView
@@ -1,0 +1,26 @@
1 +
2 +function title (s) {
3 + var m = /^\n*([^\n]{0,40})/.exec(s)
4 + return m && (m[1].length == 40 ? m[1]+'...' : m[1])
5 +}
6 +
7 +exports.needs = { sbot_get: 'first' }
8 +exports.gives = 'name'
9 +
10 +//TODO: rewrite as observable?
11 +
12 +exports.create = function (api) {
13 + return function (id, cb) {
14 + api.sbot_get(id, function (err, value) {
15 + if(err && err.name == 'NotFoundError')
16 + return cb(null, id.substring(0, 10)+'...(missing)')
17 + if(value.content.type === 'post' && 'string' === typeof value.content.text)
18 + return cb(null, title(value.content.text))
19 + else if('string' === typeof value.content.text)
20 + return cb(null, value.content.type + ':'+title(value.content.text))
21 + else
22 + return cb(null, id.substring(0, 10)+'...')
23 + })
24 + }
25 +}
26 +
modules_basic/message/render.jsView
@@ -1,0 +1,89 @@
1 +const fs = require('fs')
2 +const pull = require('pull-stream')
3 +const u = require('../../util')
4 +const h = require('../../h')
5 +
6 +exports.needs = {
7 + avatar_name: 'first',
8 + avatar_link: 'first',
9 + message_action: 'map',
10 + message_author: 'first',
11 + message_backlinks: 'first',
12 + message_content: 'first',
13 + message_content_mini: 'first',
14 + message_title: 'first',
15 + message_link: 'first',
16 + message_meta: 'map',
17 +}
18 +
19 +exports.gives = {
20 + render: true,
21 + mcss: true
22 +}
23 +
24 +exports.create = function (api) {
25 + return {
26 + message_render,
27 + mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
28 + }
29 +
30 + function message_render (msg) {
31 + var content = api.message_content_mini(msg)
32 + if (content) return mini(msg, content)
33 +
34 + content = api.message_content(msg)
35 + if (!content) return mini(msg, message_content_mini_fallback(msg))
36 +
37 + var msgEl = h('Message', {
38 + 'ev-keydown': navigateToMessageOnEnter,
39 + attributes: {
40 + tabindex: '0'
41 + }
42 + }, [
43 + h('header.author', api.message_author(msg)),
44 + h('section.title', api.message_title(msg)),
45 + h('section.meta', api.message_meta(msg)),
46 + h('section.content', content),
47 + h('section.action', api.message_action(msg)),
48 + h('footer.backlinks', api.message_backlinks(msg))
49 + ])
50 + return msgEl
51 +
52 + function navigateToMessageOnEnter (ev) {
53 + // on enter, hit first meta.
54 + if(ev.keyCode == 13) {
55 +
56 + // unless in an input
57 + if (ev.target.nodeName === 'INPUT'
58 + || ev.target.nodeName === 'TEXTAREA') return
59 +
60 + // HACK! (mw)
61 + // there's no exported api to open a new tab. :/
62 + // it's only done in `app.js` module in an`onhashchange` handler.
63 + // sooooooo yeah this shit for now :)
64 + var wtf = h('a', { href: `#${msg.key}` })
65 + msgEl.appendChild(wtf)
66 + wtf.click()
67 + msgEl.removeChild(wtf)
68 + }
69 + }
70 + }
71 +
72 + function mini(msg, el) {
73 + return h('Message -mini', {
74 + attributes: {
75 + tabindex: '0'
76 + }
77 + }, [
78 + h('header.author', api.message_author(msg, { size: 'mini' })),
79 + h('section.meta', api.message_meta(msg)),
80 + h('section.content', el)
81 + ])
82 + }
83 +}
84 +
85 +
86 +function message_content_mini_fallback(msg) {
87 + return h('code', msg.value.content.type)
88 +}
89 +
modules_basic/message/render.mcssView
@@ -1,0 +1,80 @@
1 +Message {
2 + padding: 1rem .5rem 1rem 7.5rem
3 + border-top: solid 1px gainsboro
4 + min-height: 5rem
5 +
6 + position: relative
7 + display: flex
8 + flex-direction: row
9 + flex-wrap: wrap
10 + justify-content: flex-end
11 +
12 + header.author {
13 + position: absolute
14 + left: .5rem
15 + }
16 +
17 + section.title {
18 + flex-grow: 1
19 + font-size: .9rem
20 + }
21 +
22 + section.meta {
23 + display: flex
24 + a {
25 + margin-left: .2rem
26 + $textSubtle
27 + }
28 +
29 + input{
30 + margin-right: 0
31 + order: 99
32 + }
33 + }
34 +
35 + section.content {
36 + flex-basis: 100%
37 +
38 + (img) {
39 + max-width: 100%
40 + }
41 + }
42 +
43 + section.action {
44 + flex-basis: 100%
45 + display: flex
46 + justify-content: flex-end
47 +
48 + a {
49 + margin-left: .5em
50 + }
51 + }
52 +
53 + footer.backlinks {
54 + flex-basis: 100%
55 + }
56 +
57 +
58 + -mini {
59 + font-size: .9rem
60 + justify-content: flex-start
61 + padding: .25rem .5rem
62 + min-height: inherit
63 +
64 + header.author {
65 + order: 0
66 + position: initial
67 + left: initial
68 + }
69 +
70 + section.content {
71 + order: 1
72 + flex-basis: initial
73 + flex-grow: 1
74 + }
75 +
76 + section.meta {
77 + order: 2
78 + }
79 + }
80 +}
modules_basic/message-author.mcssView
@@ -1,38 +1,0 @@
1-MessageAuthor {
2- display: flex
3- flex-direction: column
4-
5- section {
6- -image {
7- margin-bottom: .3rem
8- }
9-
10- -name {
11- max-width: 7rem
12- a { $textPrimary }
13- }
14-
15- -timestamp {
16-
17- }
18- }
19-
20- -mini {
21- flex-direction: row
22-
23- section {
24- margin-right: .5rem
25-
26- -name {
27- position: initial
28- left: initial
29- min-width: 6.5rem
30- max-width: none
31- }
32-
33- -timestamp {
34-
35- }
36- }
37- }
38-}
modules_basic/message-backlinks.jsView
@@ -1,48 +1,0 @@
1-const fs = require('fs')
2-const h = require('../h')
3-
4-exports.needs = {
5- message_name: 'first'
6-}
7-
8-exports.gives = {
9- message_backlinks: true,
10- mcss: true
11-}
12-
13-exports.create = function (api) {
14- return {
15- message_backlinks,
16- mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
17- }
18-
19- function message_backlinks (msg) {
20- var links = []
21- for(var k in CACHE) {
22- var _msg = CACHE[k]
23- var mentions = _msg.content.mentions
24-
25- if(Array.isArray(mentions)) {
26- for(var i = 0; i < mentions.length; i++)
27- if(mentions[i].link == msg.key)
28- links.push(k)
29- }
30- }
31-
32- if (links.length === 0) return null
33-
34- var hrefList = h('ul')
35- links.forEach(link => {
36- api.message_name(link, (err, name) => {
37- if (err) throw err
38- hrefList.appendChild(h('li',
39- h('a -backlink', { href: `#${link}` }, name)
40- ))
41- })
42- })
43- return h('MessageBacklinks', [
44- h('header', 'backlinks:'),
45- hrefList
46- ])
47- }
48-}
modules_basic/message-backlinks.mcssView
@@ -1,21 +1,0 @@
1-MessageBacklinks {
2- font-size: .9rem
3- margin-top: .5rem
4-
5- header {
6- $textSubtle
7- }
8-
9- ul {
10- padding-left: 1rem
11-
12- li {
13- a {
14- -backlink {
15- $textSubtle
16-
17- }
18- }
19- }
20- }
21-}
modules_basic/message-link.jsView
@@ -1,39 +1,0 @@
1-var h = require('hyperscript')
2-var ref = require('ssb-ref')
3-
4-//var first = require('../plugs').first
5-//var sbot_get = first(exports.sbot_get = [])
6-//var message_name = first(exports.message_name = [])
7-
8-exports.needs = {
9- message_name: 'first'
10-}
11-
12-exports.gives = 'message_link'
13-
14-exports.create = function (api) {
15-
16- return function (id) {
17-
18- if('string' !== typeof id)
19- throw new Error('link must be to message id')
20-
21- var link = h('a', {href: '#'+id}, id.substring(0, 10)+'...')
22-
23- if(ref.isMsg(id))
24- api.message_name(id, function (err, name) {
25- if(err) console.error(err)
26- else link.textContent = name
27- })
28-
29- return link
30- }
31-}
32-
33-
34-
35-
36-
37-
38-
39-
modules_basic/message-name.jsView
@@ -1,26 +1,0 @@
1-
2-function title (s) {
3- var m = /^\n*([^\n]{0,40})/.exec(s)
4- return m && (m[1].length == 40 ? m[1]+'...' : m[1])
5-}
6-
7-exports.needs = { sbot_get: 'first' }
8-exports.gives = 'message_name'
9-
10-//TODO: rewrite as observable?
11-
12-exports.create = function (api) {
13- return function (id, cb) {
14- api.sbot_get(id, function (err, value) {
15- if(err && err.name == 'NotFoundError')
16- return cb(null, id.substring(0, 10)+'...(missing)')
17- if(value.content.type === 'post' && 'string' === typeof value.content.text)
18- return cb(null, title(value.content.text))
19- else if('string' === typeof value.content.text)
20- return cb(null, value.content.type + ':'+title(value.content.text))
21- else
22- return cb(null, id.substring(0, 10)+'...')
23- })
24- }
25-}
26-
modules_basic/message.jsView
@@ -1,89 +1,0 @@
1-const fs = require('fs')
2-const pull = require('pull-stream')
3-const u = require('../util')
4-const h = require('../h')
5-
6-exports.needs = {
7- avatar_name: 'first',
8- avatar_link: 'first',
9- message_action: 'map',
10- message_author: 'first',
11- message_backlinks: 'first',
12- message_content: 'first',
13- message_content_mini: 'first',
14- message_title: 'first',
15- message_link: 'first',
16- message_meta: 'map',
17-}
18-
19-exports.gives = {
20- message_render: true,
21- mcss: true
22-}
23-
24-exports.create = function (api) {
25- return {
26- message_render,
27- mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
28- }
29-
30- function message_render (msg) {
31- var content = api.message_content_mini(msg)
32- if (content) return mini(msg, content)
33-
34- content = api.message_content(msg)
35- if (!content) return mini(msg, message_content_mini_fallback(msg))
36-
37- var msgEl = h('Message', {
38- 'ev-keydown': navigateToMessageOnEnter,
39- attributes: {
40- tabindex: '0'
41- }
42- }, [
43- h('header.author', api.message_author(msg)),
44- h('section.title', api.message_title(msg)),
45- h('section.meta', api.message_meta(msg)),
46- h('section.content', content),
47- h('section.action', api.message_action(msg)),
48- h('footer.backlinks', api.message_backlinks(msg))
49- ])
50- return msgEl
51-
52- function navigateToMessageOnEnter (ev) {
53- // on enter, hit first meta.
54- if(ev.keyCode == 13) {
55-
56- // unless in an input
57- if (ev.target.nodeName === 'INPUT'
58- || ev.target.nodeName === 'TEXTAREA') return
59-
60- // HACK! (mw)
61- // there's no exported api to open a new tab. :/
62- // it's only done in `app.js` module in an`onhashchange` handler.
63- // sooooooo yeah this shit for now :)
64- var wtf = h('a', { href: `#${msg.key}` })
65- msgEl.appendChild(wtf)
66- wtf.click()
67- msgEl.removeChild(wtf)
68- }
69- }
70- }
71-
72- function mini(msg, el) {
73- return h('Message -mini', {
74- attributes: {
75- tabindex: '0'
76- }
77- }, [
78- h('header.author', api.message_author(msg, { size: 'mini' })),
79- h('section.meta', api.message_meta(msg)),
80- h('section.content', el)
81- ])
82- }
83-}
84-
85-
86-function message_content_mini_fallback(msg) {
87- return h('code', msg.value.content.type)
88-}
89-
modules_basic/message.mcssView
@@ -1,80 +1,0 @@
1-Message {
2- padding: 1rem .5rem 1rem 7.5rem
3- border-top: solid 1px gainsboro
4- min-height: 5rem
5-
6- position: relative
7- display: flex
8- flex-direction: row
9- flex-wrap: wrap
10- justify-content: flex-end
11-
12- header.author {
13- position: absolute
14- left: .5rem
15- }
16-
17- section.title {
18- flex-grow: 1
19- font-size: .9rem
20- }
21-
22- section.meta {
23- display: flex
24- a {
25- margin-left: .2rem
26- $textSubtle
27- }
28-
29- input{
30- margin-right: 0
31- order: 99
32- }
33- }
34-
35- section.content {
36- flex-basis: 100%
37-
38- (img) {
39- max-width: 100%
40- }
41- }
42-
43- section.action {
44- flex-basis: 100%
45- display: flex
46- justify-content: flex-end
47-
48- a {
49- margin-left: .5em
50- }
51- }
52-
53- footer.backlinks {
54- flex-basis: 100%
55- }
56-
57-
58- -mini {
59- font-size: .9rem
60- justify-content: flex-start
61- padding: .25rem .5rem
62- min-height: inherit
63-
64- header.author {
65- order: 0
66- position: initial
67- left: initial
68- }
69-
70- section.content {
71- order: 1
72- flex-basis: initial
73- flex-grow: 1
74- }
75-
76- section.meta {
77- order: 2
78- }
79- }
80-}

Built with git-ssb-web