diff --git a/client/html/post_edit_sidebar.tpl b/client/html/post_edit_sidebar.tpl
index 7eb2e467..f2bf6232 100644
--- a/client/html/post_edit_sidebar.tpl
+++ b/client/html/post_edit_sidebar.tpl
@@ -57,6 +57,14 @@
}) %>
<% } %>
+
+ <% if (ctx.canEditPostContent) { %>
+
+ <% } %>
diff --git a/client/js/controllers/post_controller.js b/client/js/controllers/post_controller.js
index edf54960..05725f1c 100644
--- a/client/js/controllers/post_controller.js
+++ b/client/js/controllers/post_controller.js
@@ -115,6 +115,9 @@ class PostController {
if (e.detail.relations !== undefined) {
post.relations = e.detail.relations;
}
+ if (e.detail.content !== undefined) {
+ post.content = e.detail.content;
+ }
post.save()
.then(() => {
misc.disableExitConfirmation();
diff --git a/client/js/controls/file_dropper_control.js b/client/js/controls/file_dropper_control.js
index 0476c13c..a2b05044 100644
--- a/client/js/controls/file_dropper_control.js
+++ b/client/js/controls/file_dropper_control.js
@@ -28,9 +28,14 @@ class FileDropperControl {
this._fileInputNode.addEventListener(
'change', e => this._evtFileChange(e));
+ this._originalHtml = this._dropperNode.innerHTML;
views.replaceContent(target, source);
}
+ reset() {
+ this._dropperNode.innerHTML = this._originalHtml;
+ }
+
_resolve(files) {
files = Array.from(files);
if (this._options.lock) {
diff --git a/client/js/controls/post_content_control.js b/client/js/controls/post_content_control.js
index b35e7382..7a0012aa 100644
--- a/client/js/controls/post_content_control.js
+++ b/client/js/controls/post_content_control.js
@@ -11,15 +11,17 @@ class PostContentControl {
this._containerNode = containerNode;
this._template = views.getTemplate('post-content');
- this._install();
-
this._currentFitFunction = {
'fit-both': this.fitBoth,
'fit-original': this.fitOriginal,
'fit-width': this.fitWidth,
'fit-height': this.fitHeight,
}[settings.get().fitMode] || this.fitBoth;
- this._currentFitFunction();
+
+ this._install();
+
+ this._post.addEventListener(
+ 'changeContent', e => this._evtPostContentChange(e));
}
fitWidth() {
@@ -73,11 +75,15 @@ class PostContentControl {
return this._viewportSizeCalculator()[1];
}
+ _evtPostContentChange(e) {
+ this._post = e.detail.post;
+ this._post.mutateContentUrl();
+ this._reinstall();
+ }
+
_resize(width, height) {
- const postContentNode =
- this._containerNode.querySelector('.post-content');
- postContentNode.style.width = width + 'px';
- postContentNode.style.height = height + 'px';
+ this._postContentNode.style.width = width + 'px';
+ this._postContentNode.style.height = height + 'px';
}
_refreshSize() {
@@ -85,18 +91,26 @@ class PostContentControl {
}
_install() {
- const postContentNode = this._template({
- post: this._post,
- });
- if (settings.get().transparencyGrid) {
- postContentNode.classList.add('transparency-grid');
- }
- this._containerNode.appendChild(postContentNode);
+ this._reinstall();
optimizedResize.add(() => this._refreshSize());
views.monitorNodeRemoval(
this._containerNode, () => { this._uninstall(); });
}
+ _reinstall() {
+ const newNode = this._template({post: this._post});
+ if (settings.get().transparencyGrid) {
+ newNode.classList.add('transparency-grid');
+ }
+ if (this._postContentNode) {
+ this._containerNode.replaceChild(newNode, this._postContentNode);
+ } else {
+ this._containerNode.appendChild(newNode);
+ }
+ this._postContentNode = newNode;
+ this._refreshSize();
+ }
+
_uninstall() {
optimizedResize.remove(() => this._refreshSize());
}
diff --git a/client/js/controls/post_edit_sidebar_control.js b/client/js/controls/post_edit_sidebar_control.js
index cb02d18e..739c388d 100644
--- a/client/js/controls/post_edit_sidebar_control.js
+++ b/client/js/controls/post_edit_sidebar_control.js
@@ -5,6 +5,7 @@ const events = require('../events.js');
const misc = require('../util/misc.js');
const views = require('../util/views.js');
const TagInputControl = require('./tag_input_control.js');
+const FileDropperControl = require('../controls/file_dropper_control.js');
const template = views.getTemplate('post-edit-sidebar');
@@ -14,6 +15,7 @@ class PostEditSidebarControl extends events.EventTarget {
this._hostNode = hostNode;
this._post = post;
this._postContentControl = postContentControl;
+ this._newPostContent = null;
views.replaceContent(this._hostNode, template({
post: this._post,
@@ -37,6 +39,24 @@ class PostEditSidebarControl extends events.EventTarget {
if (this._tagInputNode) {
this._tagControl = new TagInputControl(this._tagInputNode);
}
+
+ if (this._contentInputNode) {
+ this._contentFileDropper = new FileDropperControl(
+ this._contentInputNode,
+ {
+ lock: true,
+ resolve: files => {
+ this._newPostContent = files[0];
+ },
+ });
+ }
+
+ this._post.addEventListener(
+ 'changeContent', e => this._evtPostContentChange(e));
+ }
+
+ _evtPostContentChange(e) {
+ this._contentFileDropper.reset();
}
_evtSubmit(e) {
@@ -62,6 +82,10 @@ class PostEditSidebarControl extends events.EventTarget {
relations: this._relationsInputNode ?
misc.splitByWhitespace(this._relationsInputNode.value) :
undefined,
+
+ content: this._newPostContent ?
+ this._newPostContent :
+ undefined,
},
}));
}
@@ -89,6 +113,10 @@ class PostEditSidebarControl extends events.EventTarget {
get _relationsInputNode() {
return this._formNode.querySelector('.relations input');
}
+
+ get _contentInputNode() {
+ return this._formNode.querySelector('.post-content .dropper-container');
+ }
};
module.exports = PostEditSidebarControl;
diff --git a/client/js/models/post.js b/client/js/models/post.js
index b0d2a47e..4e4fb29a 100644
--- a/client/js/models/post.js
+++ b/client/js/models/post.js
@@ -24,6 +24,7 @@ class Post extends events.EventTarget {
get canvasWidth() { return this._canvasWidth || 800; }
get canvasHeight() { return this._canvasHeight || 450; }
get fileSize() { return this._fileSize || 0; }
+ get content() { throw 'Invalid operation'; }
get flags() { return this._flags; }
get tags() { return this._tags; }
@@ -40,6 +41,7 @@ class Post extends events.EventTarget {
set tags(value) { this._tags = value; }
set safety(value) { this._safety = value; }
set relations(value) { this._relations = value; }
+ set content(value) { this._content = value; }
static fromResponse(response) {
const ret = new Post();
@@ -78,6 +80,7 @@ class Post extends events.EventTarget {
}
save() {
+ const files = [];
const detail = {};
// send only changed fields to avoid user privilege violation
@@ -93,15 +96,22 @@ class Post extends events.EventTarget {
if (misc.arraysDiffer(this._relations, this._orig._relations)) {
detail.relations = this._relations;
}
+ if (this._content) {
+ files.content = this._content;
+ }
let promise = this._id ?
- api.put('/post/' + this._id, detail) :
- api.post('/posts', detail);
+ api.put('/post/' + this._id, detail, files) :
+ api.post('/posts', detail, files);
return promise.then(response => {
this._updateFromResponse(response);
this.dispatchEvent(
new CustomEvent('change', {detail: {post: this}}));
+ if (this._content) {
+ this.dispatchEvent(
+ new CustomEvent('changeContent', {detail: {post: this}}));
+ }
return Promise.resolve();
}, response => {
return Promise.reject(response.description);
@@ -177,6 +187,13 @@ class Post extends events.EventTarget {
});
}
+ mutateContentUrl() {
+ this._contentUrl =
+ this._orig._contentUrl +
+ '?bypass-cache=' +
+ Math.round(Math.random()*1000);
+ }
+
_updateFromResponse(response) {
const map = {
_id: response.id,