Commit de9af547fc412d6fb68eca7f572052cc43e7fa43
initial stab at ssb-wiki
Ev Bogue committed on 7/19/2018, 9:49:16 PMParent: 75a99ec95e4f86ed01a9d68c667ab3c928e617ca
Files changed
compose.js | changed |
index.js | changed |
render.js | changed |
style.css | changed |
style.css.json | changed |
tools.js | changed |
compose.js | ||
---|---|---|
@@ -48,12 +48,14 @@ | ||
48 | 48 … | if (opts.mentions) { |
49 | 49 … | var textarea = h('textarea.compose', opts.mentions) |
50 | 50 … | } |
51 | 51 … | |
52 … | + else if (opts.type == 'wiki') | |
53 … | + var textarea = h('textarea.compose', {placeholder: opts.placeholder || 'Write a wiki (anyone can edit)'}) | |
52 | 54 … | else if (opts.type == 'post') |
53 | - var textarea = h('textarea.compose', {placeholder: opts.placeholder || 'Write a message'}) | |
55 … | + var textarea = h('textarea.compose', {placeholder: opts.placeholder || 'Write a message (only you can edit)'}) | |
54 | 56 … | else |
55 | - var textarea = h('textarea.compose', {placeholder: opts.placeholder || 'Write a message'}, fallback.messageText) | |
57 … | + var textarea = h('textarea.compose', {placeholder: opts.placeholder || 'Write a message (only you can edit)'}, fallback.messageText) | |
56 | 58 … | |
57 | 59 … | var cancelBtn = h('button.btn', 'Cancel', { |
58 | 60 … | onclick: function () { |
59 | 61 … | var cancel |
@@ -105,9 +107,9 @@ | ||
105 | 107 … | if (opts.recps) |
106 | 108 … | msg.value.private = true |
107 | 109 … | |
108 | 110 … | console.log(msg) |
109 | - if (opts.type == 'post') | |
111 … | + if (opts.type == 'post' || opts.type == 'wiki') | |
110 | 112 … | var header = tools.header(msg) |
111 | 113 … | if (opts.type == 'update') |
112 | 114 … | var header = tools.timestamp(msg, {edited: true}) |
113 | 115 … | var preview = h('div', |
index.js | ||
---|---|---|
@@ -15,9 +15,9 @@ | ||
15 | 15 … | var nav = h('div.navbar', |
16 | 16 … | h('div.internal', |
17 | 17 … | h('li', h('a', {href: '#' + id}, h('span.avatar--small', avatar.image(id)))), |
18 | 18 … | h('li', h('a', {href: '#' + id}, avatar.name(id))), |
19 | - h('li', h('a', 'Compose', { | |
19 … | + h('li', h('a', 'New Post', { | |
20 | 20 … | onclick: function () { |
21 | 21 … | if (document.getElementById('composer')) { return } |
22 | 22 … | else { |
23 | 23 … | var currentScreen = document.getElementById('screen') |
@@ -31,8 +31,24 @@ | ||
31 | 31 … | } |
32 | 32 … | } |
33 | 33 … | } |
34 | 34 … | })), |
35 … | + h('li', h('a', 'New Wiki', { | |
36 … | + onclick: function () { | |
37 … | + if (document.getElementById('composer')) { return } | |
38 … | + else { | |
39 … | + var currentScreen = document.getElementById('screen') | |
40 … | + var opts = {} | |
41 … | + opts.type = 'wiki' | |
42 … | + var composer = h('div.content#composer', h('div.message', compose(opts))) | |
43 … | + if (currentScreen.firstChild.firstChild) { | |
44 … | + currentScreen.firstChild.insertBefore(composer, currentScreen.firstChild.firstChild) | |
45 … | + } else { | |
46 … | + currentScreen.firstChild.appendChild(composer) | |
47 … | + } | |
48 … | + } | |
49 … | + } | |
50 … | + })), | |
35 | 51 … | h('li', h('a', {href: '#' }, 'All')), |
36 | 52 … | h('li', h('a', {href: '#private' }, 'Private')), |
37 | 53 … | h('li', h('a', {href: '#mentions' }, 'Mentions')), |
38 | 54 … | h('li', h('a', {href: '#key' }, 'Key')), |
render.js | |||
---|---|---|---|
@@ -92,10 +92,69 @@ | |||
92 | 92 … | //message.appendChild(h('pre', tools.rawJSON(msg.value.content))) | |
93 | 93 … | return message | |
94 | 94 … | } | |
95 | 95 … | ||
96 | - else if (msg.value.content.type == 'post') { | ||
96 … | + else if (msg.value.content.type == 'wiki') { | ||
97 … | + var fallback = {} | ||
98 … | + | ||
97 | 99 … | var opts = { | |
100 … | + type: 'wiki', | ||
101 … | + branch: msg.key | ||
102 … | + } | ||
103 … | + | ||
104 … | + if (msg.value.content.root) | ||
105 … | + opts.root = msg.value.content.root | ||
106 … | + else | ||
107 … | + opts.root = msg.key | ||
108 … | + | ||
109 … | + message.appendChild(tools.header(msg)) | ||
110 … | + | ||
111 … | + message.appendChild(h('div.message__body', tools.markdown(msg.value.content.text))) | ||
112 … | + | ||
113 … | + pull( | ||
114 … | + sbot.query({query: [{$filter: {value: {content: {type: 'edit', original: msg.key}}}}], limit: 100, live: true}), | ||
115 … | + pull.drain(function (update) { | ||
116 … | + if (update.sync) { | ||
117 … | + } else { | ||
118 … | + var newMessage = h('div', tools.markdown(update.value.content.text)) | ||
119 … | + var latest = h('div.message__body', | ||
120 … | + tools.timestamp(update, {edited: true}), | ||
121 … | + newMessage | ||
122 … | + ) | ||
123 … | + message.replaceChild(latest, message.childNodes[message.childNodes.length - 2]) | ||
124 … | + fallback.messageText = update.value.content.text | ||
125 … | + opts.updated = update.key | ||
126 … | + opts.original = msg.key | ||
127 … | + } | ||
128 … | + }) | ||
129 … | + ) | ||
130 … | + | ||
131 … | + var buttons = h('div.buttons') | ||
132 … | + | ||
133 … | + buttons.appendChild(h('button.btn', 'Edit wiki', { | ||
134 … | + onclick: function () { | ||
135 … | + opts.type = 'edit' | ||
136 … | + if (!fallback.messageText) | ||
137 … | + fallback.messageText = msg.value.content.text | ||
138 … | + | ||
139 … | + if (!opts.updated) | ||
140 … | + opts.updated = msg.key | ||
141 … | + opts.original = msg.key | ||
142 … | + | ||
143 … | + var r = message.childNodes.length - 1 | ||
144 … | + fallback.buttons = message.childNodes[r] | ||
145 … | + message.removeChild(message.childNodes[r]) | ||
146 … | + var compose = h('div#edit:' + msg.key.substring(0, 44), composer(opts, fallback)) | ||
147 … | + message.replaceChild(compose, message.lastElementChild) | ||
148 … | + } | ||
149 … | + })) | ||
150 … | + | ||
151 … | + buttons.appendChild(tools.star(msg)) | ||
152 … | + message.appendChild(buttons) | ||
153 … | + return message | ||
154 … | + | ||
155 … | + } else if (msg.value.content.type == 'post') { | ||
156 … | + var opts = { | ||
98 | 157 … | type: 'post', | |
99 | 158 … | branch: msg.key | |
100 | 159 … | } | |
101 | 160 … | var fallback = {} |
style.css | ||
---|---|---|
@@ -97,9 +97,9 @@ | ||
97 | 97 … | top: 0; |
98 | 98 … | } |
99 | 99 … | |
100 | 100 … | .navbar .internal { |
101 | - max-width: 680px; | |
101 … | + max-width: 97%; | |
102 | 102 … | margin-left: auto; |
103 | 103 … | margin-right: auto; |
104 | 104 … | } |
105 | 105 … |
style.css.json | ||
---|---|---|
@@ -1,1 +1,1 @@ | ||
1 | -"body {\n margin: 0;\n background: #141414;\n font-family: sans-serif;\n color: #d5d5d5;\n font-size: 14px; \n line-height: 20px;\n}\n\n#screen {\n position: absolute;\n top: 35px;\n bottom: 0px;\n left: 0px;\n right: 0px;\n}\n\n.hyperscroll {\n width: 100%;\n}\n\n.search {\n margin-top: 1.5px;\n float: right;\n width: 200px;\n}\n\n.header {\n padding-bottom: .7em;\n border-bottom: 1px solid #252525;\n}\n\nh1, h2, h3, h4, h5, h6 {\n font-size: 1.2em;\n margin-top: .35ex;\n}\n\nhr {\n border: solid #222;\n clear: both;\n border-width: 1px 0 0;\n height: 0;\n margin-bottom: .9em;\n}\n\n\np {\n margin-top: .35ex;\n margin-bottom: 10px;\n}\n\n/*a {\n color: #00aaff;\n text-decoration: none;\n}\n\na:hover,\na:focus {\n color: #0088cc;\n text-decoration: underline;\n}*/\n\na {\n color: white;\n *text-decoration: none;\n}\n\na:hover {\n color: #ddd;\n}\n\n.navbar a {\n color: #999;\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n text-decoration: none;\n}\n\n.navbar a:hover, .navbar a:focus {\n color: #fff;\n text-decoration: none;\n}\n\n.navbar {\n background: #1b1b1b;\n background: linear-gradient(#222, #111);\n border-bottom: 1px solid #252525;\n}\n\n.navbar {\n width: 100%;\n position: fixed;\n z-index: 1000;\n margin: 0;\n padding-top: .3em;\n padding-bottom: .3em;\n left: 0; right: 0;\n top: 0;\n}\n\n.navbar .internal {\n max-width: 680px;\n margin-left: auto;\n margin-right: auto;\n}\n\n.navbar li {\n margin-top: .3em;\n float: left;\n margin-right: .6em;\n margin-left: .3em;\n list-style-type: none;\n}\n\n.navbar li.right {\n padding-left: .4em;\n padding-right: .4em;\n margin-top: .3em;\n margin-right: 1.7em;\n float: right;\n list-style-type: none;\n background: #333;\n border-radius: 100%;\n}\n\n.content {\n max-width: 680px;\n margin-left: auto;\n margin-right: auto;\n}\n\n.hyperscroll > .content {\n max-width: 680px;\n margin-left: auto;\n margin-right: auto;\n}\n\n.message, .message > *, .navbar, .navbar > * {\n animation: fadein .5s;\n}\n\n@keyframes fadein {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.message, .embedded {\n display: block;\n margin: .6em;\n background: #111;\n padding: .7em;\n border-radius: 3px;\n border: 1px solid #252525;\n}\n\n.embedded {\n padding-left: 1em;\n}\n\n.message:hover, .embedded:hover {\n background: #141414;\n}\n\n.message img, .message video {\n max-width: 100%;\n}\n\nimg {\n border-radius: 3px;\n}\n\n.timestamp, .votes {\n float: right;\n}\n \n.avatar--small img {\n vertical-align: top;\n width: 1.4em;\n height: 1.4em;\n margin-right: .2em;\n}\n\n.avatar--medium img {\n float: left;\n vertical-align: top;\n width: 5em;\n height: 5em;\n margin-right: .5em;\n margin-bottom: .5em;\n}\n\n.compose, textarea, input {\n font-family: sans-serif;\n font-size: 14px;\n line-height: 20px;\n background: #111;\n color: #ccc;\n border: none;\n border-radius: 3px;\n}\n\ntextarea {\n width: 100%;\n height: 100px;\n}\n\n.compose:hover {\n background: #141414;\n}\n\n.compose:focus {\n outline: none;\n}\n\n.emoji {\n padding: .2em;\n}\n\n.right {\n float: right;\n}\n\n.emoji {\n *float: left;\n width: 1em;\n vertical-align: top;\n}\n\npre {\n width: 100%;\n display: block;\n}\n\ncode {\n display: inline-block;\n vertical-align: bottom;\n}\n\ncode, pre {\noverflow: auto;\nword-break: break-all;\nword-wrap: break-word;\nwhite-space: pre;\nwhite-space: -moz-pre-wrap;\nwhite-space: pre-wrap;\nwhite-space: pre\\9;\n}\n\ncode, pre {\n font-size: 12px;\n color: #ccc;\n}\n\ncode {\n color: #ccc;\n}\n\npre {\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 20px;\n}\n\nbutton {margin: 0; margin-top: -.2em;}\n\ninput {width: 88%; }\n\n#profile input {width: 50%;}\n\n.btn {\n display: inline-block;\n *display: inline;\n padding: 2px 6px;\n margin-bottom: 0;\n margin-right: .2em;\n font-size: 14px;\n line-height: 20px;\n color: #d5d5d5;\n text-align: center;\n text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75);\n vertical-align: middle;\n cursor: pointer;\n background-color: #222;\n border: 1px solid #222;\n border-radius: 4px;\n}\n\n\n.btn:hover,\n.btn:focus,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n color: white;\n background-color: black;\n}\n\n.btn:active,\n.btn.active {\n background-color: #111;\n}\n\n.btn:first-child {\n *margin-left: 0;\n}\n\n" | |
1 … | +"body {\n margin: 0;\n background: #141414;\n font-family: sans-serif;\n color: #d5d5d5;\n font-size: 14px; \n line-height: 20px;\n}\n\n#screen {\n position: absolute;\n top: 35px;\n bottom: 0px;\n left: 0px;\n right: 0px;\n}\n\n.hyperscroll {\n width: 100%;\n}\n\n.search {\n margin-top: 1.5px;\n float: right;\n width: 200px;\n}\n\n.header {\n padding-bottom: .7em;\n border-bottom: 1px solid #252525;\n}\n\nh1, h2, h3, h4, h5, h6 {\n font-size: 1.2em;\n margin-top: .35ex;\n}\n\nhr {\n border: solid #222;\n clear: both;\n border-width: 1px 0 0;\n height: 0;\n margin-bottom: .9em;\n}\n\n\np {\n margin-top: .35ex;\n margin-bottom: 10px;\n}\n\n/*a {\n color: #00aaff;\n text-decoration: none;\n}\n\na:hover,\na:focus {\n color: #0088cc;\n text-decoration: underline;\n}*/\n\na {\n color: white;\n *text-decoration: none;\n}\n\na:hover {\n color: #ddd;\n}\n\n.navbar a {\n color: #999;\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n text-decoration: none;\n}\n\n.navbar a:hover, .navbar a:focus {\n color: #fff;\n text-decoration: none;\n}\n\n.navbar {\n background: #1b1b1b;\n background: linear-gradient(#222, #111);\n border-bottom: 1px solid #252525;\n}\n\n.navbar {\n width: 100%;\n position: fixed;\n z-index: 1000;\n margin: 0;\n padding-top: .3em;\n padding-bottom: .3em;\n left: 0; right: 0;\n top: 0;\n}\n\n.navbar .internal {\n max-width: 97%;\n margin-left: auto;\n margin-right: auto;\n}\n\n.navbar li {\n margin-top: .3em;\n float: left;\n margin-right: .6em;\n margin-left: .3em;\n list-style-type: none;\n}\n\n.navbar li.right {\n padding-left: .4em;\n padding-right: .4em;\n margin-top: .3em;\n margin-right: 1.7em;\n float: right;\n list-style-type: none;\n background: #333;\n border-radius: 100%;\n}\n\n.content {\n max-width: 680px;\n margin-left: auto;\n margin-right: auto;\n}\n\n.hyperscroll > .content {\n max-width: 680px;\n margin-left: auto;\n margin-right: auto;\n}\n\n.message, .message > *, .navbar, .navbar > * {\n animation: fadein .5s;\n}\n\n@keyframes fadein {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.message, .embedded {\n display: block;\n margin: .6em;\n background: #111;\n padding: .7em;\n border-radius: 3px;\n border: 1px solid #252525;\n}\n\n.embedded {\n padding-left: 1em;\n}\n\n.message:hover, .embedded:hover {\n background: #141414;\n}\n\n.message img, .message video {\n max-width: 100%;\n}\n\nimg {\n border-radius: 3px;\n}\n\n.timestamp, .votes {\n float: right;\n}\n \n.avatar--small img {\n vertical-align: top;\n width: 1.4em;\n height: 1.4em;\n margin-right: .2em;\n}\n\n.avatar--medium img {\n float: left;\n vertical-align: top;\n width: 5em;\n height: 5em;\n margin-right: .5em;\n margin-bottom: .5em;\n}\n\n.compose, textarea, input {\n font-family: sans-serif;\n font-size: 14px;\n line-height: 20px;\n background: #111;\n color: #ccc;\n border: none;\n border-radius: 3px;\n}\n\ntextarea {\n width: 100%;\n height: 100px;\n}\n\n.compose:hover {\n background: #141414;\n}\n\n.compose:focus {\n outline: none;\n}\n\n.emoji {\n padding: .2em;\n}\n\n.right {\n float: right;\n}\n\n.emoji {\n *float: left;\n width: 1em;\n vertical-align: top;\n}\n\npre {\n width: 100%;\n display: block;\n}\n\ncode {\n display: inline-block;\n vertical-align: bottom;\n}\n\ncode, pre {\noverflow: auto;\nword-break: break-all;\nword-wrap: break-word;\nwhite-space: pre;\nwhite-space: -moz-pre-wrap;\nwhite-space: pre-wrap;\nwhite-space: pre\\9;\n}\n\ncode, pre {\n font-size: 12px;\n color: #ccc;\n}\n\ncode {\n color: #ccc;\n}\n\npre {\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 20px;\n}\n\nbutton {margin: 0; margin-top: -.2em;}\n\ninput {width: 88%; }\n\n#profile input {width: 50%;}\n\n.btn {\n display: inline-block;\n *display: inline;\n padding: 2px 6px;\n margin-bottom: 0;\n margin-right: .2em;\n font-size: 14px;\n line-height: 20px;\n color: #d5d5d5;\n text-align: center;\n text-shadow: 0 1px 1px rgba(0, 0, 0, 0.75);\n vertical-align: middle;\n cursor: pointer;\n background-color: #222;\n border: 1px solid #222;\n border-radius: 4px;\n}\n\n\n.btn:hover,\n.btn:focus,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n color: white;\n background-color: black;\n}\n\n.btn:active,\n.btn.active {\n background-color: #111;\n}\n\n.btn:first-child {\n *margin-left: 0;\n}\n\n" |
tools.js | ||
---|---|---|
@@ -279,9 +279,9 @@ | ||
279 | 279 … | |
280 | 280 … | module.exports.timestamp = function (msg, edited) { |
281 | 281 … | var timestamp |
282 | 282 … | if (edited) |
283 | - timestamp = h('span.timestamp', 'Edited: ', h('a', {href: '#' + msg.key}, human(new Date(msg.value.timestamp)))) | |
283 … | + timestamp = h('span.timestamp', 'Edited by: ', h('a', {href: '#' + msg.value.author}, h('span.avatar--small', avatar.cachedImage(msg.value.author))), h('a', {href: '#' + msg.key}, human(new Date(msg.value.timestamp)))) | |
284 | 284 … | else |
285 | 285 … | timestamp = h('span.timestamp', h('a', {href: '#' + msg.key}, human(new Date(msg.value.timestamp)))) |
286 | 286 … | return timestamp |
287 | 287 … | } |
Built with git-ssb-web