Commit a475db3f08d588ebb0617a26b471e10e3a586a16
Merge branch 'master' of github.com:ssbc/patchwork into up-to-date
Christian Bundy committed on 6/25/2018, 7:33:24 PMParent: 793514d74e3ce980e5f410a04a892ce9a3fb919d
Parent: 2c560265d95bf0384c48f982264559ea3cb3e3a4
Files changed
locales/en.json | ||
---|---|---|
@@ -142,6 +142,18 @@ | ||
142 | 142 | "other": "You follow %s people that subscribe to this channel." |
143 | 143 | }, |
144 | 144 | " forked this discussion:": " forked this discussion:", |
145 | 145 | "(missing message)": "(missing message)", |
146 | - "self assigned a display image": "self assigned a display image" | |
147 | -} | |
146 | + "self assigned a display image": "self assigned a display image", | |
147 | + "Cannot display message.": "Cannot display message.", | |
148 | + "What would you like to call ": "What would you like to call ", | |
149 | + "Names you assign here will be publicly visible to others.": "Names you assign here will be publicly visible to others.", | |
150 | + "Update Profile": "Update Profile", | |
151 | + "OK": "OK", | |
152 | + "You have not made any changes.": "You have not made any changes.", | |
153 | + "Nothing to publish": "Nothing to publish", | |
154 | + "Edit": "Edit", | |
155 | + "Only visible to you and people that have been mentioned": "Only visible to you and people that have been mentioned", | |
156 | + "Only visible to you and other thread participants": "Only visible to you and other thread participants", | |
157 | + "This message will be public and cannot be edited or deleted": "This message will be public and cannot be edited or deleted", | |
158 | + "This message will be public and can be edited by anyone": "This message will be public and can be edited by anyone" | |
159 | +} |
modules/feed/html/rollup.js | ||
---|---|---|
@@ -118,22 +118,29 @@ | ||
118 | 118 | newSinceRefresh.add(msg.key) |
119 | 119 | unreadIds.add(msg.key) |
120 | 120 | } |
121 | 121 | |
122 | - if (updates() === 0 && msg.value.author === yourId && container.scrollTop < 500) { | |
123 | - refresh() | |
124 | - } else if (msg.value.author === yourId && content()) { | |
122 | + if (msg.value.author === yourId && content()) { | |
125 | 123 | // dynamically insert this post into the feed! (manually so that it doesn't get slow with mutant) |
126 | - var existingContainer = content().querySelector(`[data-root-id="${msg.value.content.root}"]`) | |
127 | - if (existingContainer) { | |
128 | - var replies = existingContainer.querySelector('div.replies') | |
129 | - var lastReply = existingContainer.querySelector('div.replies > .Message:last-child') | |
130 | - var previousId = lastReply ? lastReply.getAttribute('data-id') : existingContainer.getAttribute('data-root-id') | |
131 | - replies.appendChild(api.message.html.render(msg, { | |
132 | - previousId, | |
133 | - compact: false, | |
134 | - priority: 2 | |
135 | - })) | |
124 | + if (api.message.sync.root(msg)) { | |
125 | + var existingContainer = content().querySelector(`[data-root-id="${api.message.sync.root(msg)}"]`) | |
126 | + if (existingContainer) { | |
127 | + var replies = existingContainer.querySelector('div.replies') | |
128 | + var lastReply = existingContainer.querySelector('div.replies > .Message:last-child') | |
129 | + var previousId = lastReply ? lastReply.getAttribute('data-id') : existingContainer.getAttribute('data-root-id') | |
130 | + replies.appendChild(api.message.html.render(msg, { | |
131 | + previousId, | |
132 | + compact: false, | |
133 | + priority: 2 | |
134 | + })) | |
135 | + } | |
136 | + } else { | |
137 | + highlightItems.add(msg.key) | |
138 | + content().prepend( | |
139 | + renderItem(extend(msg, { | |
140 | + replies: [] | |
141 | + })) | |
142 | + ) | |
136 | 143 | } |
137 | 144 | } |
138 | 145 | |
139 | 146 | updates.set(newSinceRefresh.size) |
modules/gathering/sheet/edit.js | ||
---|---|---|
@@ -8,8 +8,9 @@ | ||
8 | 8 | exports.gives = nest('gathering.sheet.edit') |
9 | 9 | |
10 | 10 | exports.needs = nest({ |
11 | 11 | 'sheet.display': 'first', |
12 | + 'message.sheet.preview': 'first', | |
12 | 13 | 'keys.sync.id': 'first', |
13 | 14 | 'sbot.async.publish': 'first', |
14 | 15 | 'about.obs.latestValue': 'first', |
15 | 16 | 'blob.html.input': 'first', |
@@ -86,9 +87,9 @@ | ||
86 | 87 | footer: [ |
87 | 88 | h('button -save', { |
88 | 89 | 'ev-click': save, |
89 | 90 | 'disabled': publishing |
90 | - }, when(publishing, i18n('Publishing...'), i18n('Publish'))), | |
91 | + }, when(publishing, i18n('Publishing...'), i18n('Preview & Publish'))), | |
91 | 92 | h('button -cancel', { |
92 | 93 | 'ev-click': close |
93 | 94 | }, i18n('Cancel')) |
94 | 95 | ] |
@@ -116,33 +117,61 @@ | ||
116 | 117 | if (chosen.title() !== current.title()) update.title = chosen.title() || i18n('Untitled Gathering') |
117 | 118 | if (chosen.description() !== current.description()) update.description = chosen.description() |
118 | 119 | |
119 | 120 | if (Object.keys(update).length) { |
120 | - publishing.set(true) | |
121 | - ensureExists((err, id) => { | |
121 | + // gatherings consist of multiple messages (maybe none of them exist yet), so we need to | |
122 | + // construct the preview dialog manually, and override the about values | |
123 | + api.message.sheet.preview({ | |
124 | + key: id, | |
125 | + previewAbout: update, | |
126 | + publicallyEditable: true, | |
127 | + value: { | |
128 | + author: api.keys.sync.id(), | |
129 | + content: { | |
130 | + type: 'gathering' | |
131 | + } | |
132 | + } | |
133 | + }, (err, confirmed) => { | |
122 | 134 | if (err) throw err |
123 | - api.sbot.async.publish(extend({ | |
124 | - type: 'about', | |
125 | - about: id | |
126 | - }, update), (err) => { | |
127 | - if (err) { | |
128 | - publishing.set(false) | |
129 | - showDialog({ | |
130 | - type: 'error', | |
131 | - title: i18n('Error'), | |
132 | - buttons: ['OK'], | |
133 | - message: i18n('An error occurred while attempting to publish gathering.'), | |
134 | - detail: err.message | |
135 | - }) | |
136 | - } else { | |
137 | - close() | |
138 | - } | |
139 | - }) | |
135 | + if (confirmed) { | |
136 | + publish(update) | |
137 | + } | |
140 | 138 | }) |
141 | 139 | } else { |
140 | + showDialog({ | |
141 | + type: 'info', | |
142 | + title: i18n('Update Profile'), | |
143 | + buttons: [i18n('OK')], | |
144 | + message: i18n('Nothing to publish'), | |
145 | + detail: i18n('You have not made any changes.') | |
146 | + }) | |
142 | 147 | close() |
143 | 148 | } |
144 | 149 | } |
150 | + | |
151 | + function publish (update) { | |
152 | + publishing.set(true) | |
153 | + ensureExists((err, id) => { | |
154 | + if (err) throw err | |
155 | + api.sbot.async.publish(extend({ | |
156 | + type: 'about', | |
157 | + about: id | |
158 | + }, update), (err) => { | |
159 | + if (err) { | |
160 | + publishing.set(false) | |
161 | + showDialog({ | |
162 | + type: 'error', | |
163 | + title: i18n('Error'), | |
164 | + buttons: ['OK'], | |
165 | + message: i18n('An error occurred while attempting to publish gathering.'), | |
166 | + detail: err.message | |
167 | + }) | |
168 | + } else { | |
169 | + close() | |
170 | + } | |
171 | + }) | |
172 | + }) | |
173 | + } | |
145 | 174 | }) |
146 | 175 | }) |
147 | 176 | } |
148 | 177 |
modules/message/async/publish.js | ||
---|---|---|
@@ -1,42 +1,25 @@ | ||
1 | -var h = require('mutant/h') | |
2 | 1 | var nest = require('depnest') |
3 | 2 | |
4 | 3 | exports.needs = nest({ |
5 | - 'sheet.display': 'first', | |
6 | - 'message.html.render': 'first', | |
4 | + 'message.sheet.preview': 'first', | |
7 | 5 | 'sbot.async.publish': 'first', |
8 | - 'keys.sync.id': 'first', | |
9 | - 'intl.sync.i18n': 'first' | |
6 | + 'keys.sync.id': 'first' | |
10 | 7 | }) |
11 | 8 | |
12 | 9 | exports.gives = nest('message.async.publish') |
13 | 10 | |
14 | 11 | exports.create = function (api) { |
15 | - const i18n = api.intl.sync.i18n | |
16 | 12 | return nest('message.async.publish', function (content, cb) { |
17 | - api.sheet.display(function (close) { | |
18 | - return { | |
19 | - content: [ | |
20 | - api.message.html.render({value: { | |
21 | - content, | |
22 | - private: !!content.recps, | |
23 | - author: api.keys.sync.id() | |
24 | - }}) | |
25 | - ], | |
26 | - footer: [ | |
27 | - h('button -save', { 'ev-click': publish }, i18n('Confirm')), | |
28 | - h('button -cancel', { 'ev-click': cancel }, i18n('Cancel')) | |
29 | - ] | |
30 | - } | |
31 | - | |
32 | - function publish () { | |
33 | - close() | |
13 | + api.message.sheet.preview({value: { | |
14 | + content, | |
15 | + private: !!content.recps, | |
16 | + author: api.keys.sync.id() | |
17 | + }}, (err, confirmed) => { | |
18 | + if (err) throw err | |
19 | + if (confirmed) { | |
34 | 20 | api.sbot.async.publish(content, cb) |
35 | - } | |
36 | - | |
37 | - function cancel () { | |
38 | - close() | |
21 | + } else { | |
39 | 22 | cb && cb(null, false) |
40 | 23 | } |
41 | 24 | }) |
42 | 25 | return true |
modules/message/sheet/preview.js | ||
---|---|---|
@@ -1,0 +1,60 @@ | ||
1 | +var h = require('mutant/h') | |
2 | +var nest = require('depnest') | |
3 | +var when = require('mutant/when') | |
4 | + | |
5 | +exports.needs = nest({ | |
6 | + 'sheet.display': 'first', | |
7 | + 'message.html.render': 'first', | |
8 | + 'intl.sync.i18n': 'first', | |
9 | + 'emoji.sync.url': 'first' | |
10 | +}) | |
11 | + | |
12 | +exports.gives = nest('message.sheet.preview') | |
13 | + | |
14 | +exports.create = function (api) { | |
15 | + const i18n = api.intl.sync.i18n | |
16 | + return nest('message.sheet.preview', function (msg, cb) { | |
17 | + api.sheet.display(function (close) { | |
18 | + var isPrivate = msg.value.private | |
19 | + var isRoot = !msg.value.content.root | |
20 | + return { | |
21 | + content: [ | |
22 | + api.message.html.render(msg) | |
23 | + ], | |
24 | + footer: [ | |
25 | + when(isPrivate, | |
26 | + h('img', {src: api.emoji.sync.url('closed_lock_with_key')}), | |
27 | + h('img', {src: api.emoji.sync.url('globe_with_meridians')}) | |
28 | + ), | |
29 | + when(isPrivate, | |
30 | + h('div.info -private', [ | |
31 | + when(isRoot, | |
32 | + i18n('Only visible to you and people that have been mentioned'), | |
33 | + i18n('Only visible to you and other thread participants') | |
34 | + ) | |
35 | + ]), | |
36 | + h('div.info -public', [ | |
37 | + when(msg.publicallyEditable, | |
38 | + i18n('This message will be public and can be edited by anyone'), | |
39 | + i18n('This message will be public and cannot be edited or deleted') | |
40 | + ) | |
41 | + ]) | |
42 | + ), | |
43 | + h('button -save', { 'ev-click': publish }, i18n('Confirm')), | |
44 | + h('button -cancel', { 'ev-click': cancel }, i18n('Cancel')) | |
45 | + ] | |
46 | + } | |
47 | + | |
48 | + function publish () { | |
49 | + close() | |
50 | + cb(null, true) | |
51 | + } | |
52 | + | |
53 | + function cancel () { | |
54 | + close() | |
55 | + cb(null, false) | |
56 | + } | |
57 | + }) | |
58 | + return true | |
59 | + }) | |
60 | +} |
modules/profile/sheet/edit.js | ||
---|---|---|
@@ -122,8 +122,15 @@ | ||
122 | 122 | close() |
123 | 123 | } |
124 | 124 | }) |
125 | 125 | } else { |
126 | + showDialog({ | |
127 | + type: 'info', | |
128 | + title: i18n('Update Profile'), | |
129 | + buttons: [i18n('OK')], | |
130 | + message: i18n('Nothing to publish'), | |
131 | + detail: i18n('You have not made any changes.') | |
132 | + }) | |
126 | 133 | close() |
127 | 134 | } |
128 | 135 | } |
129 | 136 | }) |
plugs/message/html/render/gathering.js | ||
---|---|---|
@@ -34,40 +34,47 @@ | ||
34 | 34 | render: function (msg, opts) { |
35 | 35 | if (!isRenderable(msg)) return |
36 | 36 | |
37 | 37 | var yourId = api.keys.sync.id() |
38 | - var hidden = api.about.obs.valueFrom(msg.key, 'hidden', yourId) | |
39 | - var image = api.about.obs.latestValue(msg.key, 'image') | |
40 | - var title = api.about.obs.latestValue(msg.key, 'title') | |
41 | - var description = api.about.obs.latestValue(msg.key, 'description') | |
42 | - var location = api.about.obs.latestValue(msg.key, 'location') | |
43 | - var startDateTime = api.about.obs.latestValue(msg.key, 'startDateTime') | |
44 | - // var endDateTime = api.about.obs.latestValue(msg.key, 'endDateTime') | |
45 | - var attendees = computed([api.about.obs.groupedValues(msg.key, 'attendee')], getAttendees) | |
38 | + | |
39 | + // allow override of resolved about messages for preview in modules/gathering/sheet/edit.js | |
40 | + var about = msg.key ? extend({ | |
41 | + hidden: api.about.obs.valueFrom(msg.key, 'hidden', yourId), | |
42 | + image: api.about.obs.latestValue(msg.key, 'image'), | |
43 | + title: api.about.obs.latestValue(msg.key, 'title'), | |
44 | + description: api.about.obs.latestValue(msg.key, 'description'), | |
45 | + location: api.about.obs.latestValue(msg.key, 'location'), | |
46 | + startDateTime: api.about.obs.latestValue(msg.key, 'startDateTime') | |
47 | + }, msg.previewAbout) : msg.previewAbout | |
48 | + | |
49 | + var attendees = msg.key ? computed([api.about.obs.groupedValues(msg.key, 'attendee')], getAttendees) : [] | |
50 | + var disableActions = !!msg.previewAbout | |
51 | + | |
46 | 52 | if (!following) { |
47 | 53 | following = api.contact.obs.following(yourId) |
48 | 54 | } |
49 | 55 | |
50 | - var imageUrl = computed(image, (id) => api.blob.sync.url(id)) | |
51 | - var imageId = computed(image, (link) => (link && link.link) || link) | |
56 | + var imageUrl = computed(about.image, (id) => api.blob.sync.url(id)) | |
57 | + var imageId = computed(about.image, (link) => (link && link.link) || link) | |
52 | 58 | var content = h('GatheringCard', [ |
53 | 59 | h('div.title', [ |
54 | 60 | h('a', { |
55 | 61 | href: msg.key |
56 | - }, title), | |
62 | + }, about.title), | |
57 | 63 | h('button', { |
64 | + disabled: disableActions, | |
58 | 65 | 'ev-click': send(api.gathering.sheet.edit, msg.key) |
59 | 66 | }, 'Edit Details') |
60 | 67 | ]), |
61 | - h('div.time', computed(startDateTime, formatTime)), | |
62 | - when(image, h('a.image', { | |
68 | + h('div.time', computed(about.startDateTime, formatTime)), | |
69 | + when(about.image, h('a.image', { | |
63 | 70 | href: imageId, |
64 | 71 | style: { |
65 | 72 | 'background-image': computed(imageUrl, (url) => `url(${url})`) |
66 | 73 | } |
67 | 74 | })), |
68 | 75 | h('div.attending', [ |
69 | - h('div.title', ['Attendees', ' (', computed(attendees, (x) => x.length), ')']), | |
76 | + h('div.title', ['Attendees', ' (', computed([attendees], (x) => x.length), ')']), | |
70 | 77 | h('div.attendees', [ |
71 | 78 | map(attendees, (attendee) => { |
72 | 79 | return h('a.attendee', { |
73 | 80 | href: attendee, |
@@ -76,27 +83,32 @@ | ||
76 | 83 | }) |
77 | 84 | ]), |
78 | 85 | h('div.actions', [ |
79 | 86 | h('button -attend', { |
87 | + disabled: disableActions, | |
80 | 88 | 'ev-click': send(publishAttending, msg.key) |
81 | 89 | }, `Attending`), |
82 | 90 | h('button -attend', { |
91 | + disabled: disableActions, | |
83 | 92 | 'ev-click': send(publishNotAttending, msg.key) |
84 | 93 | }, `Can't Attend`) |
85 | 94 | ]) |
86 | 95 | ]), |
87 | - h('div.location', markdown(location)), | |
88 | - when(description, h('div.description', markdown(description))) | |
96 | + h('div.location', markdown(about.location)), | |
97 | + when(about.description, h('div.description', markdown(about.description))) | |
89 | 98 | ]) |
90 | 99 | |
100 | + var editPreview = msg.previewAbout && msg.key | |
101 | + | |
91 | 102 | var element = api.message.html.layout(msg, extend({ |
92 | 103 | content, |
93 | - miniContent: 'Added a gathering', | |
104 | + miniContent: editPreview ? 'Edited a gathering' : 'Added a gathering', | |
105 | + actions: !msg.previewAbout, | |
94 | 106 | layout: 'mini' |
95 | 107 | }, opts)) |
96 | 108 | |
97 | 109 | // hide if no title set or hidden |
98 | - var visible = computed([title, hidden], (title, hidden) => { | |
110 | + var visible = computed([about.title, about.hidden], (title, hidden) => { | |
99 | 111 | return title && !hidden |
100 | 112 | }) |
101 | 113 | |
102 | 114 | return when(visible, api.message.html.decorate(element, { |
styles/dark/gathering-editor.mcss | ||
---|---|---|
@@ -30,6 +30,7 @@ | ||
30 | 30 | border: 1px solid #CCC |
31 | 31 | padding: 10px |
32 | 32 | font-size: 120% |
33 | 33 | flex: 1 |
34 | + min-height: 100px | |
34 | 35 | } |
35 | 36 | } |
styles/dark/sheet.mcss | ||
---|---|---|
@@ -19,16 +19,21 @@ | ||
19 | 19 | overflow-y: auto |
20 | 20 | flex: 1 |
21 | 21 | } |
22 | 22 | |
23 | + img { | |
24 | + max-height: 24px; | |
25 | + } | |
26 | + | |
23 | 27 | footer { |
24 | 28 | flex-shrink: 0; |
25 | 29 | min-height: 20px; |
26 | 30 | display: flex; |
27 | 31 | justify-content: flex-end; |
28 | 32 | padding: 10px; |
29 | 33 | position: relative |
30 | 34 | border-top: 1px solid #2d2c2c |
35 | + align-items: center | |
31 | 36 | |
32 | 37 | div.info { |
33 | 38 | flex: 1 |
34 | 39 | padding: 8px |
Built with git-ssb-web