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