misuzu/assets/misuzu.js/comments/form.jsx
flashwave 7353553de7 Rewrote the comments system. (#1)
old one basically bitrotted to death, may it rinse in prosciutto

Reviewed-on: #1
Co-authored-by: flashwave <me@flash.moe>
Co-committed-by: flashwave <me@flash.moe>
2025-02-20 02:19:32 +00:00

119 lines
4.1 KiB
JavaScript

#include comments/api.js
const MszCommentsFormNotice = function(args) {
const { body } = args ?? {};
const element = <div class="comments-notice">
<div class="comments-notice-inner">{body}</div>
</div>;
return {
get element() { return element; },
};
};
const MszCommentsForm = function(args) {
const {
userInfo, catInfo, postInfo,
listing, repliesToggle, replyToggle,
} = args ?? {};
const defaultStatus = () => <>Press <kbd>enter</kbd> to submit, use <kbd>shift</kbd>+<kbd>enter</kbd> to start a new line.</>;
const status = <div class="comments-form-status-text">{defaultStatus}</div>;
const element = <form class={{ 'comments-form': true, 'comments-form-root': !postInfo }} style={`--user-colour: ${userInfo.colour}`}>
<input type="hidden" name="category" value={catInfo.name} />
{postInfo ? <input type="hidden" name="reply_to" value={postInfo.id} /> : null}
<div class="comments-form-avatar">
<img src={userInfo.avatar} alt="" width="40" height="40" class="avatar" />
</div>
<div class="comments-form-wrap">
<div class="comments-form-input">
<textarea class="input__textarea" name="body" placeholder="Share your extensive insights..." onkeydown={ev => {
if(status.classList.contains('comments-form-status-error')) {
status.classList.remove('comments-form-status-error');
$removeChildren(status);
$appendChild(status, defaultStatus);
}
if(ev.key === 'Enter' && !ev.shiftKey) {
ev.preventDefault();
element.requestSubmit();
}
if(ev.key === 'p' && ev.altKey) {
ev.preventDefault();
if(element.elements.pin)
element.elements.pin.checked = !element.elements.pin.checked;
}
}} />
</div>
<div class="comments-form-actions">
<div class="comments-form-status">{status}</div>
{userInfo.can_pin && !postInfo ? <div class="comments-form-pin"><label><input type="checkbox" name="pin" /> Pin</label></div> : null}
<div class="comments-form-post"><button class="input__button">Post</button></div>
</div>
</div>
</form>;
const forAllFields = closure => {
for(let i = 0; i < element.elements.length; ++i)
closure(element.elements[i]);
};
const setDisabled = state => {
element.classList.toggle('comments-form-disabled', state);
forAllFields(field => field.disabled = state);
};
element.onsubmit = async ev => {
ev.preventDefault();
if(element.classList.contains('comments-form-disabled'))
return;
setDisabled(true);
try {
const fields = {};
forAllFields(field => {
if(!field.name)
return;
if(field.type === 'checkbox') {
if(field.checked)
fields[field.name] = field.value;
} else
fields[field.name] = field.value;
});
listing.addPost(catInfo, userInfo, await MszCommentsApi.createPost(fields));
listing.reorder();
listing.visible = true;
if(repliesToggle) {
repliesToggle.open = true;
++repliesToggle.count;
}
if(replyToggle?.active)
replyToggle.click();
element.elements.body.value = '';
if(element.elements.pin)
element.elements.pin.checked = false;
} catch(ex) {
status.classList.add('comments-form-status-error');
status.textContent = ex;
} finally {
setDisabled(false);
}
};
return {
get element() { return element; },
focus() {
element.elements.body.focus();
},
};
};