aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcel <cel@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519>2018-08-25 22:35:46 -0700
committercel <cel@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519>2018-08-25 22:49:02 -0700
commitcfb593bcb2c4a7b62ed5bdf4a7833adf63428484 (patch)
treec133287827d520bedb44559622c56391b54f9a30
parentb957f72a8af1e561c82da17921147191a03cf9f1 (diff)
downloadpatchfoo-cfb593bcb2c4a7b62ed5bdf4a7833adf63428484.tar.gz
patchfoo-cfb593bcb2c4a7b62ed5bdf4a7833adf63428484.zip
Add about-self page
-rw-r--r--lib/about.js6
-rw-r--r--lib/serve.js169
-rw-r--r--lib/util.js18
-rw-r--r--static/styles.css1
4 files changed, 180 insertions, 14 deletions
diff --git a/lib/about.js b/lib/about.js
index 29ec125..e1c6b40 100644
--- a/lib/about.js
+++ b/lib/about.js
@@ -100,8 +100,12 @@ About.prototype.get = function (dest, cb) {
var about = aboutByFeed[author] || (aboutByFeed[author] = {})
if (c.name) about.name = c.name
if (c.title) about.title = c.title
- if (c.image) about.image = u.linkDest(c.image)
+ if (c.image) {
+ about.image = u.linkDest(c.image)
+ about.imageLink = u.toLink(c.image)
+ }
if (c.description) about.description = c.description
+ if (c.publicWebHosting) about.publicWebHosting = c.publicWebHosting
}, function (err) {
if (err) return cb(err)
// bias the author's choices by giving them an extra vote
diff --git a/lib/serve.js b/lib/serve.js
index 75e84e6..3094bb8 100644
--- a/lib/serve.js
+++ b/lib/serve.js
@@ -359,6 +359,7 @@ Serve.prototype.path = function (url) {
case '/compose': return this.compose(m[2])
case '/emojis': return this.emojis(m[2])
case '/votes': return this.votes(m[2])
+ case '/about-self': return this.aboutSelf(m[2])
}
m = /^(\/?[^\/]*)(\/.*)?$/.exec(url)
switch (m[1]) {
@@ -970,6 +971,117 @@ Serve.prototype.about = function (path) {
)
}
+Serve.prototype.aboutSelf = function (ext) {
+ var self = this
+ var id = self.app.sbot.id
+ var render = self.app.render
+
+ self.app.getAbout(id, function gotAbout(err, about) {
+ if (err) return cb(err)
+
+ var data = self.data
+ var aboutName = about.name ? String(about.name).replace(/^@/, '') : ''
+ var aboutImageLink = about.imageLink || {}
+ var name = data.name != null ?
+ data.name === '' ? null : data.name :
+ aboutName || null
+ var image = data.image_upload != null ? {
+ link: data.image_upload.link,
+ type: data.image_upload.type,
+ size: data.image_upload.size
+ } : data.image_id && data.image_id !== aboutImageLink.link ? {
+ link: data.image_id,
+ type: data.image_type,
+ size: data.image_size
+ } : aboutImageLink
+ var imageId = image.link || '/static/fallback.png'
+ var description = data.description != null ?
+ data.description === '' ? null : data.description :
+ about.description || null
+ var publicWebHosting = data.publicWebHosting != null ?
+ data.publicWebHosting === 'false' ? false :
+ data.publicWebHosting === 'null' ? null : !!data.publicWebHosting :
+ about.publicWebHosting
+
+ var content
+ if (data.preview || data.preview_raw) {
+ content = {
+ type: 'about',
+ about: id
+ }
+ if (name != aboutName) content.name = name
+ if (image.link != about.image) content.image = image
+ if (description != about.description) content.description = description
+ if (publicWebHosting != about.publicWebHosting) content.publicWebHosting = publicWebHosting
+ }
+
+ pull(
+ ph('section', {}, [
+ ph('h4', 'Your public profile'),
+ ph('form', {action: '', method: 'post', enctype: 'multipart/form-data'}, [
+ ph('div', [
+ '@', ph('input', {id: 'name', name: 'name', placeholder: 'name', value: name})
+ ]),
+ ph('table', ph('tr', [
+ ph('td', [
+ ph('a', {href: render.toUrl(imageId)}, [
+ ph('img', {
+ class: 'ssb-avatar-image',
+ src: render.imageUrl(imageId),
+ alt: image.link || 'fallback avatar',
+ title: image.link || 'fallback avatar'
+ })
+ ])
+ ]),
+ ph('td', [
+ image.link ? ph('div', [
+ ph('small', ph('code', u.escapeHTML(image.link))),
+ ph('input', {type: 'hidden', name: 'image_id', value: image.link}), ' ',
+ ]) : '',
+ image.size ? [
+ ph('code', render.formatSize(image.size)),
+ ph('input', {type: 'hidden', name: 'image_size', value: image.size}), ' ',
+ ] : '',
+ image.type ? [
+ ph('input', {type: 'hidden', name: 'image_type', value: image.type})
+ ] : '',
+ ph('div', [
+ ph('input', {id: 'image_upload', type: 'file', name: 'image_upload'})
+ ])
+ ])
+ ])),
+ ph('textarea', {
+ id: 'description', name: 'description', placeholder: 'description',
+ rows: Math.max(4, u.rows(description))
+ }, u.escapeHTML(description)),
+ ph('div', {
+ title: 'Allow your messages to be hosted on public viewer websites'
+ }, [
+ ph('label', {for: 'publicWebHosting'}, 'Public web hosting: '),
+ ph('select', {name: 'publicWebHosting', id: 'publicWebHosting'}, [
+ ph('option', {value: 'true', selected: publicWebHosting}, 'yes'),
+ ph('option', {value: 'false', selected: publicWebHosting === false}, 'no'),
+ ph('option', {value: 'null', selected: publicWebHosting == null}, '…'),
+ ])
+ ]),
+ ph('p', {class: 'msg-right'}, [
+ ph('input', {type: 'submit', name: 'preview_raw', value: 'Raw'}), ' ',
+ ph('input', {type: 'submit', name: 'preview', value: 'Preview'})
+ ])
+ ]),
+ content ? [
+ self.phPreview(content, {raw: data.preview_raw})
+ ] : ''
+ ]),
+ self.wrapPage('about self: ' + id),
+ self.respondSink(200, {
+ 'Content-Type': ctype('html')
+ })
+ )
+ })
+}
+
+
Serve.prototype.type = function (path) {
var q = this.query
var type = decodeURIComponent(path.substr(1))
@@ -1692,7 +1804,9 @@ Serve.prototype.wrapUserFeed = function (isScrolled, id) {
ph('td'),
ph('td', [
ph('a', {href: render.toUrl('/contacts/' + id)}, 'contacts'), ' ',
- ph('a', {href: render.toUrl('/about/' + id)}, 'about')
+ ph('a', {href: render.toUrl('/about/' + id)}, 'about'),
+ id === myId ? [' ',
+ ph('a', {href: render.toUrl('/about-self')}, 'about-self')] : ''
])
]),
ph('tr', [
@@ -3371,18 +3485,7 @@ Serve.prototype.composer = function (opts, cb) {
}
})
- var draftMsg = {
- key: '%0000000000000000000000000000000000000000000=.sha256',
- value: {
- previous: '%0000000000000000000000000000000000000000000=.sha256',
- author: '@0000000000000000000000000000000000000000000=.ed25519',
- sequence: 1000,
- timestamp: 1000000000000,
- hash: 'sha256',
- content: content
- }
- }
- var estSize = JSON.stringify(draftMsg, null, 2).length
+ var estSize = u.estimateMessageSize(content)
sizeEl.innerHTML = self.app.render.formatSize(estSize)
if (estSize > 8192) warnings.push(h('li', 'message is too long'))
@@ -3419,6 +3522,46 @@ Serve.prototype.composer = function (opts, cb) {
}
+Serve.prototype.phPreview = function (content, opts) {
+ var msg = {
+ value: {
+ author: this.app.sbot.id,
+ timestamp: Date.now(),
+ content: content
+ }
+ }
+ opts = opts || {}
+ if (content.recps) msg.value.private = true
+ var warnings = []
+ var estSize = u.estimateMessageSize(content)
+ if (estSize > 8192) warnings.push(ph('li', 'message is too long'))
+
+ return ph('form', {action: '', method: 'post'}, [
+ ph('input', {type: 'hidden', name: 'content', value: u.escapeHTML(JSON.stringify(content))}),
+ ph('input', {type: 'hidden', name: 'redirect_to_published_msg', value: '1'}),
+ warnings.length ? [
+ ph('div', ph('em', 'warning:')),
+ ph('ul', {class: 'mentions'}, warnings)
+ ] : '',
+ ph('div', [
+ ph('em', 'draft:'), ' ',
+ u.escapeHTML(this.app.render.formatSize(estSize))
+ ]),
+ ph('table', {class: 'ssb-msgs'}, pull(
+ pull.once(msg),
+ this.app.unboxMessages(),
+ this.app.render.renderFeeds({
+ raw: opts.raw,
+ filter: this.query.filter,
+ }),
+ pull.map(u.toHTML)
+ )),
+ ph('div', {class: 'composer-actions'}, [
+ ph('input', {type: 'submit', name: 'action', value: 'publish'})
+ ])
+ ])
+}
+
function hashBuf(buf) {
var hash = crypto.createHash('sha256')
hash.update(buf)
diff --git a/lib/util.js b/lib/util.js
index 58bb4b0..c01d96c 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -165,6 +165,8 @@ u.customError = function (name) {
u.escapeHTML = function (html) {
if (!html) return ''
return html.toString('utf8')
+ .replace(/&/g, '&amp;')
+ .replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
}
@@ -242,3 +244,19 @@ u.unwrapP = function(html) {
})
}
+u.estimateMessageSize = function (content) {
+ var draftMsg = {
+ key: '%0000000000000000000000000000000000000000000=.sha256',
+ value: {
+ previous: '%0000000000000000000000000000000000000000000=.sha256',
+ author: '@0000000000000000000000000000000000000000000=.ed25519',
+ sequence: 10000,
+ timestamp: 1000000000000,
+ hash: 'sha256',
+ content: content,
+ signature: '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000==.sig.ed25519'
+ }
+ }
+
+ return JSON.stringify(draftMsg, null, 2).length
+}
diff --git a/static/styles.css b/static/styles.css
index 7b22dcf..6882559 100644
--- a/static/styles.css
+++ b/static/styles.css
@@ -174,6 +174,7 @@ td {
.id-input {
width: 60ex;
+ font-family: monospace;
}
table.ssb-object {